/*
 * This file is a part of the SteamWar software.
 *
 * Copyright (C) 2021  SteamWar.de-Serverteam
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

package de.steamwar.bausystem.region;

import de.steamwar.bausystem.region.flags.Flag;
import de.steamwar.bausystem.region.tags.Tag;
import yapion.hierarchy.types.YAPIONObject;

import java.util.EnumMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * Tags and Flags are not allowed to have overlaping names.
 */
public class FlagStorage {

	public static FlagStorage createStorage(YAPIONObject yapionObject) {
		FlagStorage flagStorage = new FlagStorage();
		for (final Flag flag : Flag.getFlags()) {
			try {
				String s = yapionObject.getPlainValue(flag.name());
				flagStorage.set(flag, flag.getFlagValueOf(s));
			} catch (Exception e) {
				flagStorage.set(flag, flag.getDefaultValue());
			}
		}
		for (final Tag tag : Tag.values()) {
			if (yapionObject.containsKey(tag.name())) {
				flagStorage.set(tag);
			}
		}
		return flagStorage;
	}

	public static YAPIONObject toYAPION(FlagStorage flagStorage) {
		YAPIONObject yapionObject = new YAPIONObject();
		for (final Flag flag : Flag.getFlags()) {
			if (flag.getDefaultValue() == flagStorage.flags.getOrDefault(flag, flag.getDefaultValue())) {
				yapionObject.remove(flag.name());
			} else {
				yapionObject.add(flag.name(), flagStorage.get(flag).getValue().name());
			}
		}
		for (Tag tag : Tag.values()) {
			if (flagStorage.tagSet.contains(tag)) {
				yapionObject.add(tag.name(), "");
			} else {
				yapionObject.remove(tag.name());
			}
		}
		return yapionObject;
	}

	protected Map<Flag, Flag.Value<?>> flags;
	protected Set<Tag> tagSet;

	public FlagStorage() {
		flags = new EnumMap<>(Flag.class);
		tagSet = new HashSet<>();
		readKeys();
	}

	public boolean set(final Flag flagType, final Flag.Value<?> value) {
		return flags.put(flagType, value) != value;
	}

	public Flag.Value<?> get(final Flag flagType) {
		return flags.getOrDefault(flagType, flagType.getDefaultValue());
	}

	public boolean set(final Tag tag) {
		return tagSet.add(tag);
	}

	public boolean remove(final Tag tag) {
		return tagSet.remove(tag);
	}

	public boolean is(final Tag tag) {
		return tagSet.contains(tag);
	}

	private void readKeys() {
		for (final Flag flag : Flag.getFlags()) {
			flags.put(flag, flag.getDefaultValue());
		}
	}
}