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

import com.comphenix.tinyprotocol.TinyProtocol;
import com.mojang.authlib.GameProfile;
import de.steamwar.core.Core;
import de.steamwar.core.ProtocolWrapper;
import de.steamwar.fightsystem.ArenaMode;
import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.FightSystem;
import de.steamwar.fightsystem.record.GlobalRecorder;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Sound;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;

import java.util.Collection;
import java.util.HashSet;

public class Fight {
    private Fight(){}

    @Getter
    private static final FightTeam redTeam = new FightTeam(Config.TeamRedName, Config.TeamRedColor, Config.TeamRedSpawn, Config.RedPasteRegion, Config.RedExtendRegion, Config.RedRotate, false, Config.RedLeader);
    @Getter
    private static final FightTeam blueTeam = new FightTeam(Config.TeamBlueName, Config.TeamBlueColor, Config.TeamBlueSpawn, Config.BluePasteRegion, Config.BlueExtendRegion, Config.BlueRotate, true, Config.BlueLeader);
    private static final Collection<FightTeam> teams = new HashSet<>();
    static {
        teams.add(redTeam);
        teams.add(blueTeam);
    }

    public static FightTeam getPlayerTeam(LivingEntity player) {
        if(redTeam.isPlayerInTeam(player))
            return redTeam;
        if(blueTeam.isPlayerInTeam(player))
            return blueTeam;
        return null;
    }

    public static FightTeam getOpposite(FightTeam fightTeam) {
        if(fightTeam == redTeam)
            return blueTeam;
        else if(fightTeam == blueTeam)
            return redTeam;

        throw new IllegalArgumentException();
    }

    public static FightPlayer getFightPlayer(LivingEntity player) {
        if(redTeam.isPlayerInTeam(player))
            return redTeam.getFightPlayer(player);
        if(blueTeam.isPlayerInTeam(player))
            return blueTeam.getFightPlayer(player);
        return null;
    }

    public static boolean fighting(LivingEntity player) {
        return getPlayerTeam(player) != null;
    }

    public static Collection<FightTeam> teams() {
        return teams;
    }

    public static FightTeam getUnrotated() {
        return Config.blueNegZ() ? Fight.getBlueTeam() : Fight.getRedTeam();
    }

    public static void playSound(Sound sound, float volume, float pitch) {
        GlobalRecorder.getInstance().soundAtPlayer(sound.name(), volume, pitch);
        //volume: max. 100, pitch: max. 2
        if(Core.getVersion() >= 18)
            Bukkit.getServer().getOnlinePlayers().forEach(player -> player.playSound(player, sound, volume, pitch));
        else
            Bukkit.getServer().getOnlinePlayers().forEach(player -> player.playSound(player.getLocation(), sound, volume, pitch));
    }

    public static FightTeam getTeamByName(String name) {
        if(redTeam.getName().equalsIgnoreCase(name))
            return redTeam;
        if(blueTeam.getName().equalsIgnoreCase(name))
            return blueTeam;
        return null;
    }

    @SuppressWarnings("deprecation")
    public static void setPlayerGamemode(Player player, GameMode gameMode) {
        player.setGameMode(gameMode);

        if(gameMode == GameMode.SPECTATOR) {
            for(Player currentPlayer : Bukkit.getServer().getOnlinePlayers()) {
                if(currentPlayer.getUniqueId() != player.getUniqueId() && currentPlayer.getGameMode() == GameMode.SPECTATOR) {
                    currentPlayer.hidePlayer(player);
                    player.hidePlayer(currentPlayer);
                }
            }

            if(Config.test() || Config.isReferee(player))
                return;

            Bukkit.getScheduler().runTaskLater(FightSystem.getPlugin(), () -> {
                if(!player.isOnline())
                    return;
                pseudoSpectator(player, true);
            }, 1);
        }else if(gameMode == GameMode.SURVIVAL) {
            for(Player currentPlayer : Bukkit.getServer().getOnlinePlayers()) {
                if(currentPlayer.getUniqueId() != player.getUniqueId() && currentPlayer.getGameMode() == GameMode.SPECTATOR) {
                    currentPlayer.showPlayer(player);
                    player.showPlayer(currentPlayer);
                }
            }
        }
    }

    public static void pseudoSpectator(Player player, boolean enable) {
        TinyProtocol.instance.sendPacket(player, ProtocolWrapper.impl.playerInfoPacketConstructor(ProtocolWrapper.PlayerInfoAction.GAMEMODE, new GameProfile(player.getUniqueId(), player.getName()), enable ? GameMode.CREATIVE : GameMode.SPECTATOR));
    }

    public static boolean publicOnly() {
        if (Config.OnlyPublicSchematics) {
            return true;
        }
        if (Config.IgnorePublicOnly || ArenaMode.RankedEvent.contains(Config.mode)) {
            return false;
        }
        if (redTeam.getLeader() == null || blueTeam.getLeader() == null) {
            return false;
        }
        return redTeam.isPublicsOnly() || blueTeam.isPublicsOnly();
    }
}
