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

import de.steamwar.linkage.Linked;
import de.steamwar.messages.Chatter;
import de.steamwar.messages.Message;
import de.steamwar.persistent.Subserver;
import de.steamwar.sql.EventFight;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.Team;
import lombok.Getter;
import net.kyori.adventure.text.event.ClickEvent;

import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.TimeUnit;

import static de.steamwar.persistent.Storage.eventServer;

@Linked
public class EventStarter {

    @Getter
    private static final Map<Integer, String> spectatePorts = new HashMap<>();

    public static void addSpectateServer(int port, String command) {
        spectatePorts.put(port, command);
    }

    public EventStarter() {
        EventFight.loadAllComingFights();
        VelocityCore.schedule(this::run).repeat(10, TimeUnit.SECONDS).schedule();
    }

    public static Map<Integer, Subserver> getEventServer() {
        return eventServer;
    }

    private void run() {
        if (eventServer.entrySet().removeIf(entry -> Subserver.getSubserver(entry.getValue().getServer()) == null)) {
            EventFight.loadAllComingFights();
        }
        Queue<EventFight> fights = EventFight.getFights();

        EventFight next;
        while ((next = nextFight(fights)) != null) {
            Team blue = Team.byId(next.getTeamBlue());
            Team red = Team.byId(next.getTeamRed());

            //Don't start EventServer if not the event bungee
            String command;
            if (VelocityCore.get().getConfig().isEventmode() || next.getSpectatePort() == null) {
                ServerStarter starter = new ServerStarter().event(next);

                starter.callback(subserver -> {
                    eventServer.put(blue.getTeamId(), subserver);
                    eventServer.put(red.getTeamId(), subserver);

                    if (VelocityCore.get().getConfig().isEventmode()) {
                        VelocityCore.getProxy().getAllPlayers().forEach(player -> {
                            SteamwarUser user = SteamwarUser.get(player.getUniqueId());
                            if (user.getTeam() == blue.getTeamId() || user.getTeam() == red.getTeamId()) {
                                subserver.sendPlayer(player);
                            }
                        });
                    }
                }).start();

                command = "/event " + blue.getTeamKuerzel();
            } else {
                command = "/" + spectatePorts.get(next.getSpectatePort());
            }
            Chatter.broadcast().system("EVENT_FIGHT_BROADCAST", new Message("EVENT_FIGHT_BROADCAST_HOVER"), ClickEvent.runCommand(command), blue.getTeamColor(), blue.getTeamName(), red.getTeamColor(), red.getTeamName());
        }
        EventFight.clearActiveFightsCache();
    }

    private EventFight nextFight(Queue<EventFight> fights) {
        EventFight next = fights.peek();
        if (next == null) return null;

        if (!next.getStartTime().before(new Timestamp(System.currentTimeMillis()))) return null;

        return fights.poll();
    }
}
