// • ▌ ▄ ·.  ▄▄▄·  ▄▄ • ▪   ▄▄· ▄▄▄▄·  ▄▄▄·  ▐▄▄▄  ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀  █▪▀▀▀ ▀  ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀  ▀  ▀ ▀▀  █▪ ▀▀▀
//      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.ClientNetMsg;
import engine.net.client.msg.ErrorPopupMsg;
import engine.net.client.msg.UpdateGoldMsg;
import engine.net.client.msg.VendorSellMsg;
import engine.objects.*;

import java.util.ArrayList;

public class VendorSellMsgHandler extends AbstractClientMsgHandler {

    public VendorSellMsgHandler() {
        super(VendorSellMsg.class);
    }

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

        PlayerCharacter pc = origin.getPlayerCharacter();
        PlayerCharacter player = SessionManager.getPlayerCharacter(origin);
        Dispatch dispatch;

        if (player == null)
            return true;

        CharacterItemManager itemMan = player.charItemManager;

        if (itemMan == null)
            return true;

        VendorSellMsg vendorSellMsg = (VendorSellMsg) baseMsg;

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

        if (npc == null)
            return true;

        Item gold = itemMan.getGoldInventory();

        if (gold == null)
            return true;

        if (origin.sellLock.tryLock()) {
            try {
                Item sell;
                int cost = 0;


                if (npc.charItemManager.getInventoryCount() > 150) {
                    if (npc.getParentZone() != null && npc.getParentZone().playerCityUUID == 0) {
                        ArrayList<Item> inv = npc.getInventory();
                        for (int i = 0; i < 20; i++) {
                            try {
                                Item toRemove = inv.get(i);
                                if (toRemove != null)
                                    npc.charItemManager.delete(toRemove);
                            } catch (Exception e) {
                                break;
                            }

                        }
                    }

                }

                // Early exit sanity check

                if (vendorSellMsg.getItemType() == Enum.GameObjectType.Item.ordinal() == false)
                    return true;

                sell = Item.getFromCache(vendorSellMsg.getItemID());

                if (sell == null)
                    return true;

                //get item to sell

                if (sell.template == null)
                    return true;

                if (npc.getParentZone() != null && npc.getParentZone().playerCityUUID != 0)
                    if (!npc.charItemManager.hasRoomInventory(sell.template.item_wt)) {
                        ErrorPopupMsg.sendErrorPopup(player, 21);
                        return true;
                    }

                if (!sell.validForInventory(origin, player, itemMan))
                    return true;

                //get goldItem cost to sell

                cost = sell.template.item_value;

                //apply damaged value reduction
                float damagedModifier = sell.combat_health_current / sell.template.combat_health_full;
                cost *= damagedModifier;

                float bargain = player.getBargain();
                float profit = npc.getBuyPercent(player) + bargain;

                if (profit > 1)
                    profit = 1;

                cost *= profit;

                if (gold.getNumOfItems() + cost > 10000000)
                    return true;

                if (gold.getNumOfItems() + cost < 0)
                    return true;

                //TODO make sure npc can buy item type
                //test room available for item on npc

                //                                 if (!npc.isStatic() && npc.getCharItemManager().getInventoryCount() > 150) {
                //                                   //  chatMan.chatSystemInfo(pc, "This vendor's inventory is full");
                //                                     return;
                //                                 }

                //make sure item is in player inventory

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

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

                if (npc.getParentZone().playerCityUUID == 0)
                    building = null;

                //make sure npc can afford item

                if (building != null && !building.hasFunds(cost)) {
                    ErrorPopupMsg.sendErrorPopup(player, 17);
                    return true;
                }

                if (building != null && (building.getStrongboxValue() - cost) < 0) {
                    ErrorPopupMsg.sendErrorPopup(player, 17);
                    return true;
                }

                //TODO transfer item and goldItem transfer should be handled together incase failure
                //transfer the item

                if (!itemMan.sellToNPC(sell, npc))
                    return true;

                if (!itemMan.sellToNPC(building, cost, sell))
                    return true;

                //handle goldItem transfer

                if (sell == null)
                    return true;

                // ***REFACTOR: SellToNpc sends this message, is this a duplicate?

                //update player's goldItem count
                UpdateGoldMsg ugm = new UpdateGoldMsg(player);
                ugm.configure();

                dispatch = Dispatch.borrow(player, ugm);
                DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);

                //send the sell message back to update player
                vendorSellMsg.setItemType(sell.getObjectType().ordinal());
                vendorSellMsg.setItemID(sell.getObjectUUID());
                vendorSellMsg.setUnknown01(cost); //not sure if this is correct

                dispatch = Dispatch.borrow(player, vendorSellMsg);
                DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);

            } finally {
                origin.sellLock.unlock();
            }
        } else {
            ErrorPopupMsg.sendErrorPopup(player, 12);
        }

        // Send ping to client

        dispatch = Dispatch.borrow(pc, vendorSellMsg);
        DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY);

        return true;
    }

}