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

import lombok.Getter;

import java.util.*;

public enum FightState {
    PRE_LEADER_SETUP,
    PRE_SCHEM_SETUP,
    POST_SCHEM_SETUP,
    PRE_RUNNING,
    RUNNING,
    SPECTATE;

    public static final Set<FightState> All = Collections.unmodifiableSet(EnumSet.allOf(FightState.class));

    public static final Set<FightState> PreLeaderSetup = Collections.unmodifiableSet(EnumSet.of(PRE_LEADER_SETUP));
    public static final Set<FightState> PreSchemSetup = Collections.unmodifiableSet(EnumSet.of(PRE_SCHEM_SETUP));
    public static final Set<FightState> PostSchemSetup = Collections.unmodifiableSet(EnumSet.of(POST_SCHEM_SETUP));
    public static final Set<FightState> PreRunning = Collections.unmodifiableSet(EnumSet.of(PRE_RUNNING));
    public static final Set<FightState> Running = Collections.unmodifiableSet(EnumSet.of(RUNNING));
    public static final Set<FightState> Spectate = Collections.unmodifiableSet(EnumSet.of(SPECTATE));

    public static final Set<FightState> Setup = Collections.unmodifiableSet(EnumSet.of(PRE_LEADER_SETUP, PRE_SCHEM_SETUP, POST_SCHEM_SETUP));
    public static final Set<FightState> Ingame = Collections.unmodifiableSet(EnumSet.of(PRE_RUNNING, RUNNING));
    public static final Set<FightState> TeamFix = Collections.unmodifiableSet(EnumSet.of(PRE_RUNNING, RUNNING, SPECTATE));
    public static final Set<FightState> Schem = Collections.unmodifiableSet(EnumSet.complementOf(EnumSet.of(PRE_LEADER_SETUP, PRE_SCHEM_SETUP)));
    public static final Set<FightState> Recording = Collections.unmodifiableSet(EnumSet.complementOf(EnumSet.of(PRE_LEADER_SETUP, PRE_SCHEM_SETUP, SPECTATE)));
    public static final Set<FightState> AntiRunning = Collections.unmodifiableSet(EnumSet.complementOf(EnumSet.of(RUNNING)));
    public static final Set<FightState> AntiIngame = Collections.unmodifiableSet(EnumSet.complementOf(EnumSet.of(PRE_RUNNING, RUNNING)));
    public static final Set<FightState> AntiSpectate = Collections.unmodifiableSet(EnumSet.complementOf(EnumSet.of(SPECTATE)));

    @Getter
    private static final Map<IStateDependent, Boolean> stateDependentFeatures = new HashMap<>();
    @Getter
    private static FightState fightState = PRE_LEADER_SETUP;

    public static void registerStateDependent(IStateDependent stateDependent){
        if(stateDependent.enabled().isEmpty())
            return;
        boolean enabled = stateDependent.enabled().contains(fightState);
        stateDependentFeatures.put(stateDependent, enabled);
        if(enabled)
            stateDependent.enable();
    }

    public static void setFightState(FightState state){
        fightState = state;

        for(Map.Entry<IStateDependent, Boolean> feature : stateDependentFeatures.entrySet()){
            //Enable feature if should be enabled and currently disabled
            if(feature.getKey().enabled().contains(fightState) && !feature.getValue()){
                feature.getKey().enable();
                feature.setValue(true);
            }

            //Disable feature if should be disabled and currently enabled
            if(!feature.getKey().enabled().contains(fightState) && feature.getValue()){
                feature.getKey().disable();
                feature.setValue(false);
            }
        }
    }

    public static boolean setup(){
        return Setup.contains(fightState);
    }

    public static boolean ingame(){
        return Ingame.contains(fightState);
    }

    public static boolean infight(){
        return fightState == RUNNING;
    }
}
