/*
 * 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.loader;

import de.steamwar.bausystem.region.FlagStorage;
import de.steamwar.bausystem.region.GlobalRegion;
import de.steamwar.bausystem.region.Prototype;
import de.steamwar.bausystem.worlddata.WorldData;
import lombok.experimental.UtilityClass;
import org.bukkit.Bukkit;
import yapion.hierarchy.diff.DiffChange;
import yapion.hierarchy.diff.YAPIONDiff;
import yapion.hierarchy.types.YAPIONObject;
import yapion.hierarchy.types.YAPIONType;
import yapion.parser.YAPIONParser;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

@UtilityClass
public class RegionLoader {

    private YAPIONObject loaded = null;
    public static final File file = new File(Bukkit.getWorlds().get(0).getWorldFolder(), "regions.yapion");

    public void load() {
        YAPIONObject yapionObject = null;
        try (BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(file))) {
            yapionObject = YAPIONParser.parse(bufferedInputStream);
        } catch (IOException e) {
            throw new SecurityException(e.getMessage(), e);
        }

        if (loaded != null && new YAPIONDiff(loaded, yapionObject).getDiffs().stream().anyMatch(diffBase -> !(diffBase instanceof DiffChange))) {
            throw new SecurityException("Version was not the specified version needed.");
        }
        loaded = yapionObject;

        YAPIONObject optionsYapionObject = WorldData.getRegionsData();
        yapionObject.forEach((key, yapionAnyType) -> {
            if (key.equals("global")) {
                return;
            }
            if (!(yapionAnyType instanceof YAPIONObject)) {
                return;
            }

            YAPIONObject regionConfig = (YAPIONObject) yapionAnyType;
            YAPIONObject regionData = new YAPIONObject();
            if (optionsYapionObject.containsKey(key, YAPIONType.OBJECT)) {
                regionData = optionsYapionObject.getObject(key);
            } else {
                optionsYapionObject.add(key, regionData);
            }

            Prototype.generateRegion(key, regionConfig, regionData);
        });

        YAPIONObject globalOptions = optionsYapionObject.getObject("global");
        if (globalOptions == null) {
            globalOptions = new YAPIONObject();
            optionsYapionObject.add("global", globalOptions);
        }
        FlagStorage flagStorage;
        if (globalOptions.containsKey("flagStorage", YAPIONType.OBJECT)) {
            flagStorage = FlagStorage.createStorage(globalOptions.getObject("flagStorage"));
        } else {
            flagStorage = new FlagStorage();
        }
        new GlobalRegion(flagStorage, globalOptions);
    }
}
