/*
 *   This file is a part of the SteamWar software.
 *
 *   Copyright (C) 2023  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.features.script.lua.libs;

import de.steamwar.bausystem.features.loader.Loader;
import de.steamwar.bausystem.region.GlobalRegion;
import de.steamwar.bausystem.region.Region;
import de.steamwar.bausystem.region.flags.Flag;
import de.steamwar.bausystem.region.flags.flagvalues.FireMode;
import de.steamwar.bausystem.region.flags.flagvalues.FreezeMode;
import de.steamwar.bausystem.region.flags.flagvalues.ProtectMode;
import de.steamwar.bausystem.region.flags.flagvalues.TNTMode;
import de.steamwar.linkage.Linked;
import org.bukkit.entity.Player;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.OneArgFunction;

import java.util.function.Supplier;

@Linked
public class RegionLib implements LuaLib {

    @Override
    public String name() {
        return "region";
    }

    private LuaTable create(Supplier<Region> region, Player player) {
        LuaTable table = LuaValue.tableOf();

        table.set("name", getter(() -> region.get().getName()));
        table.set("type", getter(() -> {
            Region region1 = region.get();
            if (region1 instanceof GlobalRegion) {
                return "global";
            } else {
                return region1.getPrototype().getName();
            }
        }));

        LuaValue tntLib = LuaValue.tableOf();
        tntLib.set("mode", getter(() -> region.get().getPlain(Flag.TNT, TNTMode.class).name()));
        tntLib.set("enabled", getter(() -> region.get().getPlain(Flag.TNT, TNTMode.class) != TNTMode.DENY));
        tntLib.set("onlyTb", getter(() -> region.get().getPlain(Flag.TNT, TNTMode.class) == TNTMode.ONLY_TB));
        tntLib.set("onlyBuild", getter(() -> region.get().getPlain(Flag.TNT, TNTMode.class) == TNTMode.ONLY_BUILD));

        table.set("tnt", tntLib);

        table.set("fire", getter(() -> region.get().getPlain(Flag.FIRE, FireMode.class) == FireMode.ALLOW));
        table.set("freeze", getter(() -> region.get().getPlain(Flag.FREEZE, FreezeMode.class) == FreezeMode.ACTIVE));
        table.set("protect", getter(() -> region.get().getPlain(Flag.PROTECT, ProtectMode.class) == ProtectMode.ACTIVE));

        //LuaValue traceLib = LuaValue.tableOf();
        //traceLib.set("active", getter(() -> !region.get().isGlobal() && Recorder.INSTANCE.get(region.get()) instanceof ActiveTracer));
        //traceLib.set("auto", getter(() -> !region.get().isGlobal() && Recorder.INSTANCE.get(region.get()) instanceof AutoTraceRecorder));
        //traceLib.set("status", getter(() -> Recorder.INSTANCE.get(region.get()).scriptState()));
        //traceLib.set("time", getter(() -> Recorder.INSTANCE.get(region.get()).scriptTime()));

        //table.set("trace", traceLib);

        Loader loader = Loader.getLoader(player);
        table.set("loader", getter(() -> loader == null ? "OFF" : loader.getStage().name()));
        
        table.set("copyPoint", getter(() -> toPos(region.get().getCopyPoint())));
        table.set("minPointBuild", getter(() -> toPos(region.get().getMinPointBuild())));
        table.set("maxPointBuild", getter(() -> toPos(region.get().getMaxPointBuild())));
        table.set("minPointBuildExtension", getter(() -> toPos(region.get().getMinPointBuildExtension())));
        table.set("maxPointBuildExtension", getter(() -> toPos(region.get().getMaxPointBuildExtension())));
        table.set("testblockPoint", getter(() -> toPos(region.get().getTestBlockPoint())));
        table.set("minPointTestblock", getter(() -> toPos(region.get().getMinPointTestblock())));
        table.set("maxPointTestblock", getter(() -> toPos(region.get().getMaxPointTestblock())));
        table.set("minPointTestblockExtension", getter(() -> toPos(region.get().getMinPointTestblockExtension())));
        table.set("maxPointTestblockExtension", getter(() -> toPos(region.get().getMaxPointTestblockExtension())));

        return table;
    }

    @Override
    public LuaTable get(Player player) {
        LuaTable table = create(() -> Region.getRegion(player.getLocation()), player);
        table.set("get", new OneArgFunction() {
            @Override
            public LuaValue call(LuaValue arg) {
                return create(() -> Region.getREGION_MAP().get(arg.checkjstring()), player);
            }
        });

        table.set("list", getter(() -> LuaValue.listOf(Region.getREGION_MAP().values().stream().map(region -> create(() -> region, player)).toArray(LuaTable[]::new))));

        return table;
    }
}
