package engine.net.client.handlers;

import engine.Enum;
import engine.Enum.ItemType;
import engine.exception.MsgSendException;
import engine.gameManager.*;
import engine.net.Dispatch;
import engine.net.DispatchMessage;
import engine.net.client.ClientConnection;
import engine.net.client.msg.ActivateNPCMessage;
import engine.net.client.msg.ClientNetMsg;
import engine.net.client.msg.ManageCityAssetsMsg;
import engine.objects.*;
import org.pmw.tinylog.Logger;

import java.util.ArrayList;

/*
 * @Author:
 * @Summary: Processes application protocol message which keeps
 * client's tcp connection open.
 */
public class ActivateNPCMsgHandler extends AbstractClientMsgHandler {

    public ActivateNPCMsgHandler() {
        super(ActivateNPCMessage.class);
    }

    @Override
    protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {

        ActivateNPCMessage msg;
        PlayerCharacter player;
        Building building;
        Contract contract;
        CharacterItemManager itemMan;
        Zone zone;

        msg = (ActivateNPCMessage) baseMsg;
        player = SessionManager.getPlayerCharacter(origin);
        building = BuildingManager.getBuildingFromCache(msg.buildingUUID());

        if (player == null || building == null)
            return false;

        ArrayList<Item> ItemLists = new ArrayList<>();

        // Filter hirelings by slot type

        for (Item hirelings : player.getInventory()) {
            if (hirelings.getItemBase().getType().equals(ItemType.CONTRACT)) {

                contract = DbManager.ContractQueries.GET_CONTRACT(hirelings.getItemBase().getUUID());

                if (contract == null)
                    continue;

                if (contract.canSlotinBuilding(building))
                    ItemLists.add(hirelings);

                if(building.getBlueprint().getBuildingGroup().equals(Enum.BuildingGroup.TOL)){
                    if(contract.getContractID() == 899)//alchemist
                        ItemLists.add(hirelings);

                    if(contract.getContractID() == 866)//banker
                        ItemLists.add(hirelings);

                    if(contract.getContractID() == 865)//siege engineer
                        ItemLists.add(hirelings);
                }
                if(building.getBlueprint().getBuildingGroup().equals(Enum.BuildingGroup.SIEGETENT)){
                    if(contract.getContractID() == 865)//siege engineer
                        ItemLists.add(hirelings);
                }
            }
        }

        if (msg.getUnknown01() == 1) {
            //Request npc list to slot
            ActivateNPCMessage anm = new ActivateNPCMessage();
            anm.setSize(ItemLists.size());
            anm.setItemList(ItemLists);
            Dispatch dispatch = Dispatch.borrow(player, anm);
            DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
        }

        if (msg.getUnknown01() == 0) {

            //Slot npc

            if (building.getBlueprintUUID() == 0) {
                ChatManager.chatSystemError(player, "Unable to load Blueprint for Building Mesh " + building.getMeshUUID());
                return false;
            }

            if (building.getBlueprint().getSlotsForRank(building.getRank()) == building.getHirelings().size())
                return false;

            Item contractItem = Item.getFromCache(msg.getContractItem());

            if (contractItem == null)
                return false;
            if (msg.getContractItem() == 850) {//runemaster
                for (AbstractCharacter abs : building.getHirelings().keySet()) {
                    NPC npc = (NPC) abs;
                    if (npc.contract.getContractID() == 850)
                        return false; //can only have 1 runemaster
                }
            }

            if (!player.getCharItemManager().doesCharOwnThisItem(contractItem.getObjectUUID())) {
                Logger.error(player.getName() + "has attempted to place Hireling : " + contractItem.getName() + "without a valid contract!");
                return false;
            }

            itemMan = player.getCharItemManager();

            zone = ZoneManager.findSmallestZone(building.getLoc());

            if (zone == null)
                return false;

            contract = DbManager.ContractQueries.GET_CONTRACT(contractItem.getItemBase().getUUID());

            if (contract == null)
                return false;

            // Check if contract can be slotted in this building
            //Logger.error("inserting contract: " + contract.getContractID());
            if (contract.canSlotinBuilding(building) == false) {
                boolean override = false;
                if (building.getBlueprint().getBuildingGroup().equals(Enum.BuildingGroup.TOL)) {
                    if (contract.getContractID() == 899)//alchemist
                        override = true;

                    if (contract.getContractID() == 866)//banker
                        override = true;

                    if (contract.getContractID() == 865)//siege engineer
                        override = true;
                }
                if (building.getBlueprint().getBuildingGroup().equals(Enum.BuildingGroup.SIEGETENT)) {
                    if (contract.getContractID() == 865)//siege engineer
                        override = true;
                }
                if(building.getBlueprint().getBuildingGroup().equals(Enum.BuildingGroup.SIEGETENT)){
                    if(contract.getContractID() == 865)//siege engineer
                        override = true;
                }
                if(override == false) {
                    Logger.error("failed at override with contract: " + contract.getContractID());
                    return false;
                }
            }
            //Logger.error("override successful: " + contract.getContractID());
            if (!BuildingManager.addHireling(building, player, zone, contract, contractItem))
                return false;

            itemMan.delete(contractItem);
            itemMan.updateInventory();

            ManageCityAssetsMsg mca1 = new ManageCityAssetsMsg(player, building);

            mca1.actionType = 3;

            mca1.setTargetType(building.getObjectType().ordinal());
            mca1.setTargetID(building.getObjectUUID());
            mca1.setTargetType3(building.getObjectType().ordinal());
            mca1.setTargetID3(building.getObjectUUID());
            mca1.setAssetName1(building.getName());
            mca1.setUnknown54(1);
            Dispatch dispatch = Dispatch.borrow(player, mca1);
            DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);


        }

        return true;
    }

}
