/*
 *   This file is a part of the SteamWar software.
 *
 *   Copyright (C) 2025 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.fightsystem.winconditions;

import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.countdown.Countdown;
import de.steamwar.fightsystem.fight.Fight;
import de.steamwar.fightsystem.fight.FightTeam;
import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.StateDependent;
import de.steamwar.fightsystem.states.StateDependentListener;
import de.steamwar.fightsystem.states.StateDependentTask;
import de.steamwar.fightsystem.utils.Message;
import de.steamwar.fightsystem.utils.SWSound;
import de.steamwar.linkage.Linked;
import org.bukkit.Location;
import org.bukkit.entity.EntityType;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.entity.EntitySpawnEvent;

import java.util.HashMap;
import java.util.Map;

@Linked
public class WinconditionTimeTechKO extends Wincondition implements Listener {

    private static final int TECH_KO_HALF_TIME = Config.GameModeConfig.WinConditionParams.TechKoTime / 2;

    private final Map<Integer, FightTeam> spawnLocations = new HashMap<>();
    private final Map<FightTeam, TechKOCountdown> countdowns = new HashMap<>();
    private final Map<FightTeam, Integer> currentTime = new HashMap<>();

    public WinconditionTimeTechKO() {
        super("TechKO");

        new StateDependentListener(Winconditions.TIME_TECH_KO, FightState.Running, this);
        new StateDependentTask(Winconditions.TIME_TECH_KO, FightState.Running, this::run, 20, 20);
        new StateDependent(Winconditions.TIME_TECH_KO, FightState.Running) {
            @Override
            public void enable() {
                Fight.teams().forEach(team -> currentTime.put(team, TECH_KO_HALF_TIME));
            }

            @Override
            public void disable() {
                spawnLocations.clear();
                currentTime.clear();
                countdowns.values().forEach(Countdown::disable);
                countdowns.clear();
            }
        }.register();
    }

    @EventHandler
    public void onSpawn(EntitySpawnEvent e) {
        if (e.getEntityType() != EntityType.TNT) return;

        Location location = e.getLocation();
        for (FightTeam team : Fight.teams()) {
            if (team.getExtendRegion().inRegion(location)) {
                spawnLocations.put(e.getEntity().getEntityId(), team);
                break;
            }
        }
    }

    @EventHandler
    public void onExplode(EntityExplodeEvent e) {
        if (e.getEntityType() != EntityType.TNT) return;

        FightTeam spawn = spawnLocations.remove(e.getEntity().getEntityId());
        if (spawn == null) return;

        Location location = e.getLocation();
        for (FightTeam team : Fight.teams()) {
            if (team != spawn && team.getExtendRegion().inRegion(location)) {
                currentTime.put(spawn, TECH_KO_HALF_TIME);
                TechKOCountdown countdown = countdowns.remove(spawn);
                if (countdown != null) countdown.disable();
            }
        }
    }

    private void run() {
        currentTime.entrySet().forEach(entry -> {
            entry.setValue(entry.getValue() - 1);
            if (entry.getValue() == 0) {
                countdowns.put(entry.getKey(), new TechKOCountdown(entry.getKey(), TECH_KO_HALF_TIME));
            }
        });
    }

    private class TechKOCountdown extends Countdown {
        private final FightTeam team;

        public TechKOCountdown(FightTeam team, int countdownTime) {
            super(countdownTime, new Message("TECHKO_COUNTDOWN", team.getColoredName()), SWSound.BLOCK_NOTE_PLING, false);
            this.team = team;
            super.enable();
        }

        @Override
        public void countdownFinished() {
            win(Fight.getOpposite(team), "WIN_TECHKO", team.getColoredName());
        }
    }
}
