package engine.gameManager;

import engine.Enum;
import engine.InterestManagement.WorldGrid;
import engine.math.Vector3fImmutable;
import engine.net.Dispatch;
import engine.net.DispatchMessage;
import engine.net.client.msg.HotzoneChangeMsg;
import engine.net.client.msg.chat.ChatSystemMsg;
import engine.objects.*;
import engine.server.MBServerStatics;
import org.pmw.tinylog.Logger;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;

public class HotzoneManager {
    public static Long lastPulseTime = 0L;
    public static HashMap<Guild, ArrayList<PlayerCharacter>> playersPresent;
    public static Mob hotzoneMob = null;
    public static boolean three_quarter_health = false;
    public static boolean half_health = false;
    public static boolean quarter_health = false;
    public static long lastAnnounce = 0L;
    public static void SelectRandomHotzone(){
        if(hotzoneMob != null){
            hotzoneMob.killCharacter("Hotzone Over");
            hotzoneMob.despawn();
            hotzoneMob.spawnTime = 1000000000;
            DbManager.MobQueries.DELETE_MOB( hotzoneMob);
        }
        Random random = new Random();
        Zone newHotzone = null;
        while (newHotzone == null || newHotzone.getObjectUUID() == 931 || newHotzone.getObjectUUID() == 913)
            newHotzone = (Zone) ZoneManager.macroZones.toArray()[random.nextInt(ZoneManager.macroZones.size())];
        ZoneManager.setHotZone(newHotzone);
        ZoneManager.hotZone = newHotzone;
        int R8UUId = 0;
        switch(random.nextInt(5)) {
            case 1:
                R8UUId = 14152;
                break;
            case 2:
                R8UUId = 14179;
                break;
            case 3:
                R8UUId = 14180;
                break;
            case 4:
                R8UUId = 14220;
                break;
            default:
                R8UUId = 14319;
                break;
        }
        Mob created = Mob.createMob(R8UUId,newHotzone.getLoc(), Guild.getErrantGuild(),true,newHotzone,null,0,"",85);
        if(created == null){
            Logger.error("Failed To Generate Hotzone R8 Mob");
            return;
        }
        ChatSystemMsg chatMsg = new ChatSystemMsg(null, created.getFirstName() + " has spawned in " + newHotzone.getName() + ". Glory and riches await adventurers who dare defeat it!");
        chatMsg.setMessageType(10);
        chatMsg.setChannel(Enum.ChatChannelType.SYSTEM.getChannelID());
        DispatchMessage.dispatchMsgToAll(chatMsg);

        created.bindLoc = newHotzone.getLoc();
        created.runAfterLoad();
        WorldGrid.addObject(created,created.bindLoc.x,created.bindLoc.z);
        created.teleport(created.bindLoc);
        created.BehaviourType = Enum.MobBehaviourType.Aggro;
        hotzoneMob = created;
        created.setHealth(100000);
        created.setResists(new Resists("Dropper"));
        GenerateHotzoneEpicLoot(created);
        ZoneManager.hotZone = newHotzone;

        for(PlayerCharacter player : SessionManager.getAllActivePlayerCharacters()) {
            HotzoneChangeMsg hcm = new HotzoneChangeMsg(Enum.GameObjectType.Zone.ordinal(), ZoneManager.hotZone.getObjectUUID());
            Dispatch dispatch = Dispatch.borrow(player, hcm);
            DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
        }
        three_quarter_health = false;
        half_health = false;
        quarter_health = false;
    }

    public static void GenerateHotzoneEpicLoot(Mob mob) {
        mob.getCharItemManager().clearInventory();
        Random random = new Random();
        int roll = random.nextInt(100);
        int itemId;
        ItemBase runeBase;
        if (roll >= 90) {
            //35 or 40
            roll = ThreadLocalRandom.current().nextInt(HellgateManager.static_rune_ids_high.size() + 1);
            itemId = HellgateManager.static_rune_ids_high.get(0);
            try {
                itemId = HellgateManager.static_rune_ids_high.get(roll);
            } catch (Exception e) {

            }
            runeBase = ItemBase.getItemBase(itemId);
            if (runeBase != null) {
                MobLoot rune = new MobLoot(mob, runeBase, true);

                if (rune != null)
                    mob.getCharItemManager().addItemToInventory(rune);
            }
        } else if (roll >= 65 && roll <= 89) {
            //30,35 or 40
            roll = ThreadLocalRandom.current().nextInt(HellgateManager.static_rune_ids_mid.size() + 1);
            itemId = HellgateManager.static_rune_ids_mid.get(0);
            try {
                itemId = HellgateManager.static_rune_ids_mid.get(roll);
            } catch (Exception e) {

            }
            runeBase = ItemBase.getItemBase(itemId);
            if (runeBase != null) {
                MobLoot rune = new MobLoot(mob, runeBase, true);

                if (rune != null)
                    mob.getCharItemManager().addItemToInventory(rune);
            }
        } else {
            //5-30
            roll = ThreadLocalRandom.current().nextInt(HellgateManager.static_rune_ids_low.size() + 1);
            itemId = HellgateManager.static_rune_ids_low.get(0);
            try {
                itemId = HellgateManager.static_rune_ids_low.get(roll);
            } catch (Exception ignored) {

            }
            runeBase = ItemBase.getItemBase(itemId);
            if (runeBase != null) {
                MobLoot rune = new MobLoot(mob, runeBase, true);

                if (rune != null)
                    mob.getCharItemManager().addItemToInventory(rune);
            }
        }
        roll = ThreadLocalRandom.current().nextInt(1, 101);
        if (roll >= 95) {
            //glass
            int glassID = LootManager.rollRandomItem(126);
            ItemBase glassItem = ItemBase.getItemBase(glassID);
            if (glassItem != null) {
                MobLoot glass = new MobLoot(mob, glassItem, true);

                if (glass != null)
                    mob.getCharItemManager().addItemToInventory(glass);
            }
        }

        roll = ThreadLocalRandom.current().nextInt(1, 101);
        if (roll >= 95) {
            //r8 banescroll
            int baneID = 910018;
            ItemBase baneItem = ItemBase.getItemBase(baneID);
            if (baneItem != null) {
                MobLoot bane = new MobLoot(mob, baneItem, true);

                if (bane != null)
                    mob.getCharItemManager().addItemToInventory(bane);
            }
        }

        roll = ThreadLocalRandom.current().nextInt(1, 101);
        if (roll >= 95) {
            //guard captain
            roll = ThreadLocalRandom.current().nextInt(LootManager.racial_guard_uuids.size() + 1);
            itemId = LootManager.racial_guard_uuids.get(0);
            try {
                itemId = LootManager.racial_guard_uuids.get(roll);
            } catch (Exception e) {

            }
            runeBase = ItemBase.getItemBase(itemId);
            if (runeBase != null) {
                MobLoot rune = new MobLoot(mob, runeBase, true);

                if (rune != null)
                    mob.getCharItemManager().addItemToInventory(rune);
            }
        }
    }

    public static void ClearHotzone(){
        ZoneManager.hotZone = null;
        for(PlayerCharacter player : SessionManager.getAllActivePlayerCharacters()) {
            HotzoneChangeMsg hcm = new HotzoneChangeMsg(Enum.GameObjectType.Zone.ordinal(), 0);
            Dispatch dispatch = Dispatch.borrow(player, hcm);
            DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
        }
    }

    public static void pulse(){
        if(HotzoneManager.playersPresent == null)
            HotzoneManager.playersPresent = new HashMap<>();

        if(ZoneManager.hotZone == null)
            return;

        if(lastPulseTime + 5000L > System.currentTimeMillis())
            return;

        lastPulseTime = System.currentTimeMillis();

        //handle world announcements for HZ boss
        if(hotzoneMob != null){
            float health = hotzoneMob.getHealth();
            if(health < 75000 && health > 50000 && !three_quarter_health){
                //mob at 50%-75% health
                three_quarter_health = true;
                String name = hotzoneMob.getName();
                ChatSystemMsg chatMsg = new ChatSystemMsg(null, name + " In The Hotzone Is At 75% Health");
                chatMsg.setMessageType(10);
                chatMsg.setChannel(Enum.ChatChannelType.SYSTEM.getChannelID());
                DispatchMessage.dispatchMsgToAll(chatMsg);
            }else if(health < 50000 && health > 25000 && !half_health){
                //mob ta 25%-50% health
                half_health = true;
                String name = hotzoneMob.getName();
                ChatSystemMsg chatMsg = new ChatSystemMsg(null, name + " In The Hotzone Is At 50% Health");
                chatMsg.setMessageType(10);
                chatMsg.setChannel(Enum.ChatChannelType.SYSTEM.getChannelID());
                DispatchMessage.dispatchMsgToAll(chatMsg);
            }else if(health < 25000 && !quarter_health){
                //mob under 25% health
                quarter_health = true;
                String name = hotzoneMob.getName();
                ChatSystemMsg chatMsg = new ChatSystemMsg(null, name + " In The Hotzone Is At 25% Health");
                chatMsg.setMessageType(10);
                chatMsg.setChannel(Enum.ChatChannelType.SYSTEM.getChannelID());
                DispatchMessage.dispatchMsgToAll(chatMsg);
            }else if (health > 75000){
                //mob at 75% - 100% health
                if(lastAnnounce + MBServerStatics.FIVE_MINUTES < System.currentTimeMillis()){
                    lastAnnounce = System.currentTimeMillis();
                    String name = hotzoneMob.getName();
                    ChatSystemMsg chatMsg = new ChatSystemMsg(null, name + " In The Hotzone Is Still Alive");
                    chatMsg.setMessageType(10);
                    chatMsg.setChannel(Enum.ChatChannelType.SYSTEM.getChannelID());
                    DispatchMessage.dispatchMsgToAll(chatMsg);
                }
            }
        }

        HashSet<AbstractWorldObject> inRange = WorldGrid.getObjectsInRangePartial(ZoneManager.hotZone.getLoc(),ZoneManager.hotZone.getBounds().getHalfExtents().x * 2, MBServerStatics.MASK_PLAYER);

        //clear out old players who aren't here anymore
        for(Guild nation : HotzoneManager.playersPresent.keySet()){
            for(PlayerCharacter pc : HotzoneManager.playersPresent.get(nation)){
                if (!inRange.contains(pc)) {
                    HotzoneManager.playersPresent.get(nation).remove(pc);
                    if(HotzoneManager.playersPresent.get(nation).size() < 1){
                        HotzoneManager.playersPresent.remove(nation);
                    }
                }
            }
        }

        //check status of current players/nation in vicinity
        for(AbstractWorldObject awo : inRange){
            PlayerCharacter pc = (PlayerCharacter)awo;
            Guild nation = pc.guild.getNation();
            if(HotzoneManager.playersPresent.containsKey(nation)){
                //nation already here, add to list
                if(HotzoneManager.playersPresent.get(nation).size() >= 5 && !HotzoneManager.playersPresent.get(nation).contains(pc)){
                    //more than 5, boot player out
                    MovementManager.translocate(pc, Vector3fImmutable.getRandomPointOnCircle(ZoneManager.getZoneByUUID(656).getLoc(),30f),Regions.GetRegionForTeleport(ZoneManager.getZoneByUUID(656).getLoc()));
                }
                if(!HotzoneManager.playersPresent.get(nation).contains(pc)){
                    //less than 5, allow player in
                    HotzoneManager.playersPresent.get(nation).add(pc);
                }
            }else{
                ArrayList<PlayerCharacter> newList = new ArrayList<>();
                newList.add(pc);
                HotzoneManager.playersPresent.put(nation,newList);
            }
        }
    }
}