// • ▌ ▄ ·.  ▄▄▄·  ▄▄ • ▪   ▄▄· ▄▄▄▄·  ▄▄▄·  ▐▄▄▄  ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀  █▪▀▀▀ ▀  ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀  ▀  ▀ ▀▀  █▪ ▀▀▀
//      Magicbane Emulator Project © 2013 - 2022
//                www.magicbane.com


package engine.workthreads;

import engine.Enum;
import engine.InterestManagement.WorldGrid;
import engine.db.archive.DataWarehouse;
import engine.db.archive.MineRecord;
import engine.gameManager.*;
import engine.mobileAI.Threads.MobAIThread;
import engine.net.DispatchMessage;
import engine.net.MessageDispatcher;
import engine.net.client.msg.chat.ChatSystemMsg;
import engine.objects.*;
import engine.server.MBServerStatics;
import engine.server.world.WorldServer;
import org.pmw.tinylog.Logger;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.concurrent.ConcurrentHashMap;

import static engine.server.MBServerStatics.MINE_LATE_WINDOW;

public class ZergMechanicThread implements Runnable {
public Bane bane = null;
public Mine mine = null;
public ArrayList<PlayerCharacter> affectedPlayers = new ArrayList<>();

    public ZergMechanicThread(Bane b, Mine m) {
        this.mine = m;
        this.bane = b;
    }

    @Override
    public void run() {

            if (mine != null)
                RunMineMechanic();
            if (bane != null)
                RunBaneMechanic();
    }

    public void RunMineMechanic(){
        while(mine.isActive) {
            HashSet<AbstractWorldObject> currentPlayers;
            PlayerCharacter player;

            // Gather current list of players within the zone bounds
            Building tower = BuildingManager.getBuildingFromCache(mine.getBuildingID());
            currentPlayers = WorldGrid.getObjectsInRangePartial(tower.loc, Enum.CityBoundsType.GRID.extents * 0.5f, MBServerStatics.MASK_PLAYER);

            for (AbstractWorldObject playerObject : currentPlayers) {

                if (playerObject == null)
                    continue;

                player = (PlayerCharacter) playerObject;

                if(!this.affectedPlayers.contains(player))
                    this.affectedPlayers.add(player);

                //ChatManager.chatSystemInfo(player, "TESTING ZERG MECHANIC");
                if (mine._recentMemory.containsKey(player.getObjectUUID()))
                    mine._recentMemory.remove(player.getObjectUUID());

                if (mine._playerMemory.contains(player.getObjectUUID()))
                    continue;

                mine._playerMemory.add(player.getObjectUUID());

            }
            boolean updated = false;
            try {
                mine.onExit(currentPlayers);
            } catch (Exception e) {
                Logger.error(e.getMessage());
            }
            mine.dividedPlayers = new HashMap<>();
            for (Integer playerID : mine._playerMemory) {
                player = PlayerCharacter.getFromCache(playerID);
                Guild nation = player.getGuild().getNation();
                Guild entry;
                if (mine.dividedPlayers.containsKey(nation)) {
                    mine.dividedPlayers.get(nation).add(playerID);
                } else {
                    ArrayList<Integer> newEntry = new ArrayList<>();
                    newEntry.add(playerID);
                    mine.dividedPlayers.put(nation, newEntry);
                }
            }
            for (Integer playerID : mine._playerMemory) {
                player = PlayerCharacter.getFromCache(playerID);
                if (mine.dividedPlayers.containsKey(player.getGuild().getNation())) {
                    int count = mine.dividedPlayers.get(player.getGuild().getNation()).size();
                    switch (mine.capSize) {
                        case 3:
                            player.ZergMultiplier = ZergManager.getMultiplier3Man(count);
                            break;
                        case 5:
                            player.ZergMultiplier = ZergManager.getMultiplier5Man(count);
                            break;
                        case 10:
                            player.ZergMultiplier = ZergManager.getMultiplier10Man(count);
                            break;
                        case 20:
                            player.ZergMultiplier = ZergManager.getMultiplier20Man(count);
                            break;
                    }
                    player.mineAppliedID = mine.getObjectUUID();
                } else {
                    player.ZergMultiplier = 1.0f;
                    player.mineAppliedID = 0;
                }
            }
        }

        for(PlayerCharacter player : this.affectedPlayers)
            player.ZergMultiplier = 1.0f;
    }

    public void RunBaneMechanic(){
        while(bane.getSiegePhase().equals(Enum.SiegePhase.WAR)) {
            HashSet<AbstractWorldObject> currentPlayers;

            currentPlayers = WorldGrid.getObjectsInRangePartial(bane.getCity().loc, Enum.CityBoundsType.GRID.extents * 2.0f, MBServerStatics.MASK_PLAYER);

            Guild attacker = bane.getStone().getGuild().getNation();
            Guild defender = bane.getCity().getGuild().getNation();

            ArrayList<PlayerCharacter> attackers = new ArrayList<>();
            ArrayList<PlayerCharacter> defenders = new ArrayList<>();

            for (AbstractWorldObject awo : currentPlayers) {

                if(!this.affectedPlayers.contains((PlayerCharacter)awo))
                    this.affectedPlayers.add((PlayerCharacter)awo);

                PlayerCharacter pc = (PlayerCharacter) awo;
                if (!pc.getGuild().getNation().equals(attacker) && !pc.getGuild().getNation().equals(defender)) {
                    pc.teleport(pc.bindLoc);
                    pc.ZergMultiplier = 1.0f;
                }

                if (pc.getGuild().getNation().equals(attacker))
                    attackers.add(pc);

                if (pc.getGuild().getNation().equals(defender))
                    defenders.add(pc);
            }

            //int treeRank = bane.getCity().getTOL().getRank();

            for (PlayerCharacter pc : attackers) {
                switch(bane.capSize){
                    case 10:
                        pc.ZergMultiplier = ZergManager.getMultiplier10Man(attackers.size());
                        break;
                    case 20:
                        pc.ZergMultiplier = ZergManager.getMultiplier20Man(attackers.size());
                        break;
                }
            }

            for (PlayerCharacter pc : defenders) {
                switch(bane.capSize){
                    case 10:
                        pc.ZergMultiplier = ZergManager.getMultiplier10Man(defenders.size());
                        break;
                    case 20:
                        pc.ZergMultiplier = ZergManager.getMultiplier20Man(defenders.size());
                        break;
                }
            }
        }

        for(PlayerCharacter player : this.affectedPlayers)
            player.ZergMultiplier = 1.0f;
    }

    public static void startZergThreadMine(Mine mine) {
        Thread zergMechanicThread;
        zergMechanicThread = new Thread(new ZergMechanicThread(null, mine));
        zergMechanicThread.setName(mine.getParentZone().getName() + "Mine");
        zergMechanicThread.start();
    }

    public static void startZergThreadBane(Bane bane) {
        Thread zergMechanicThread;
        zergMechanicThread = new Thread(new ZergMechanicThread(bane, null));
        zergMechanicThread.setName(bane.getCity().getGuild().getName() + "Bane");
        zergMechanicThread.start();
    }
}
