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

package engine.net.client.handlers;

import engine.Enum;
import engine.Enum.DispatchChannel;
import engine.exception.MsgSendException;
import engine.gameManager.SessionManager;
import engine.net.Dispatch;
import engine.net.DispatchMessage;
import engine.net.client.ClientConnection;
import engine.net.client.msg.BuyFromNPCMsg;
import engine.net.client.msg.ClientNetMsg;
import engine.net.client.msg.ErrorPopupMsg;
import engine.objects.*;

import java.util.ArrayList;

public class BuyFromNPCMsgHandler extends AbstractClientMsgHandler {

    public BuyFromNPCMsgHandler() {
        super(BuyFromNPCMsg.class);
    }

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

        // Member variable declaration

        BuyFromNPCMsg buyFromNPCMsg;

        // Member variable assignment

        buyFromNPCMsg = (BuyFromNPCMsg) baseMsg;
        PlayerCharacter sourcePlayer = SessionManager.getPlayerCharacter(origin);

        if (sourcePlayer == null)
            return true;

        if (origin.buyLock.tryLock()) {

            try {
                CharacterItemManager itemMan = sourcePlayer.charItemManager;

                if (itemMan == null)
                    return true;

                NPC npc = NPC.getFromCache(buyFromNPCMsg.getNPCID());

                if (npc == null)
                    return true;

                Item gold = itemMan.getGoldInventory();

                if (gold == null)
                    return true;

                Item buy = null;

                if (buyFromNPCMsg.getItemType() == Enum.GameObjectType.Item.ordinal()) {

                    ArrayList<Item> sellInventory = npc.getContract().getSellInventory();

                    if (sellInventory == null)
                        return true;

                    for (Item me : sellInventory) {

                        if (me.getObjectUUID() == buyFromNPCMsg.getItemID()) {

                            //test room available for item
                            if (!itemMan.hasRoomInventory(me.template.item_wt))
                                return true;

                            int cost = me.getMagicValue();

                            float bargain = sourcePlayer.getBargain();

                            float profit = npc.getSellPercent(sourcePlayer) - bargain;

                            if (profit < 1)
                                profit = 1;

                            cost *= profit;

                            if (gold.getNumOfItems() - cost < 0) {
                                //dont' have enough goldItem exit!
                                // chatMan.chatSystemInfo(pc, "" + "You dont have enough gold.");
                                return true;
                            }

                            Building building = (!npc.isStatic()) ? npc.getBuilding() : null;

                            if (building != null && building.getProtectionState().equals(Enum.ProtectionState.NPC))
                                building = null;

                            int buildingDeposit = cost - me.getMagicValue();

                            if (building != null && (building.getStrongboxValue() + buildingDeposit) > building.getMaxGold()) {
                                ErrorPopupMsg.sendErrorPopup(sourcePlayer, 206);
                                return true;
                            }

                            if (!itemMan.buyFromNPC(building, cost, buildingDeposit)) {
                                // chatMan.chatSystemInfo(pc, "" + "You Failed to buy the item.");
                                return true;
                            }

                            buy = Item.createItemForPlayer(sourcePlayer, me.templateID);

                            if (buy != null) {
                             //   me.transferEnchants(buy);
                                itemMan.addItemToInventory(buy);
                                //itemMan.updateInventory();
                            }
                        }
                    }
                } else if (buyFromNPCMsg.getItemType() == Enum.GameObjectType.Item.ordinal()) {

                    CharacterItemManager npcCim = npc.charItemManager;

                    if (npcCim == null)
                        return true;

                    buy = Item.getFromCache(buyFromNPCMsg.getItemID());

                    if (buy == null)
                        return true;

                    if (!npcCim.inventoryContains(buy))
                        return true;

                    //test room available for item
                    if (!itemMan.hasRoomInventory(buy.template.item_wt))
                        return true;

                    //TODO test cost and subtract goldItem

                    //TODO CHnage this if we ever put NPc city npcs in buildings.
                    int cost = buy.template.item_value;

                    if (buy.isID() || buy.isCustomValue())
                        cost = buy.getMagicValue();

                    float bargain = sourcePlayer.getBargain();

                    float profit = npc.getSellPercent(sourcePlayer) - bargain;

                    if (profit < 1)
                        profit = 1;

                    if (!buy.isCustomValue())
                        cost *= profit;
                    else
                        cost = buy.getValue();


                    if (gold.getNumOfItems() - cost < 0) {
                        ErrorPopupMsg.sendErrorPopup(sourcePlayer, 128);  // Insufficient Gold
                        return true;
                    }

                    Building building = (!npc.isStatic()) ? npc.getBuilding() : null;

                    if (building != null)
                        if (building.getProtectionState().equals(Enum.ProtectionState.NPC))
                            building = null;

                    int buildingDeposit = cost;

                    if (building != null && (building.getStrongboxValue() + buildingDeposit) > building.getMaxGold()) {
                        ErrorPopupMsg.sendErrorPopup(sourcePlayer, 206);
                        return true;
                    }

                    if (!itemMan.buyFromNPC(building, cost, buildingDeposit)) {
                        ErrorPopupMsg.sendErrorPopup(sourcePlayer, 110);
                        return true;
                    }

                    if (buy != null)
                        itemMan.buyFromNPC(buy, npc);

                } else if (buyFromNPCMsg.getItemType() == Enum.GameObjectType.MobLoot.ordinal()) {

                    CharacterItemManager npcCim = npc.charItemManager;

                    if (npcCim == null)
                        return true;

                    buy = MobLoot.getFromCache(buyFromNPCMsg.getItemID());

                    if (buy == null)
                        return true;

                    if (!npcCim.inventoryContains(buy))
                        return true;

                    //test room available for item
                    if (!itemMan.hasRoomInventory(buy.template.item_wt))
                        return true;

                    //TODO test cost and subtract goldItem

                    //TODO CHnage this if we ever put NPc city npcs in buildings.

                    int cost = buy.getMagicValue();
                    cost *= npc.getSellPercent(sourcePlayer);

                    if (gold.getNumOfItems() - cost < 0) {
                        ErrorPopupMsg.sendErrorPopup(sourcePlayer, 128);  // Insufficient Gold
                        return true;
                    }

                    Building building = (!npc.isStatic()) ? npc.getBuilding() : null;

                    if (building != null && building.getProtectionState().equals(Enum.ProtectionState.NPC))
                        building = null;
                    int buildingDeposit = cost;

                    if (building != null && (building.getStrongboxValue() + buildingDeposit) > building.getMaxGold()) {
                        ErrorPopupMsg.sendErrorPopup(sourcePlayer, 206);
                        return true;
                    }

                    if (!itemMan.buyFromNPC(building, cost, buildingDeposit))
                        return true;

                    if (buy != null)
                        itemMan.buyFromNPC(buy, npc);

                } else
                    return true;

                if (buy != null) {

                    buyFromNPCMsg.setItem(buy);
                    //send the buy message back to update player
                    //					msg.setItemType(buy.getObjectType().ordinal());
                    //					msg.setItemID(buy.getObjectUUID());
                    Dispatch dispatch = Dispatch.borrow(sourcePlayer, buyFromNPCMsg);
                    DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
                    itemMan.updateInventory();
                }

            } finally {
                origin.buyLock.unlock();
            }
        } else {
            ErrorPopupMsg.sendErrorPopup(origin.getPlayerCharacter(), 12); // All production slots taken
        }
        return true;
    }

}