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

package engine.net.client.handlers;

import engine.mbEnums;
import engine.exception.MsgSendException;
import engine.gameManager.DbManager;
import engine.gameManager.SessionManager;
import engine.net.client.ClientConnection;
import engine.net.client.msg.ClientNetMsg;
import engine.net.client.msg.ErrorPopupMsg;
import engine.net.client.msg.VendorBuyMsg;
import engine.objects.*;
import org.pmw.tinylog.Logger;

import java.util.ArrayList;

public class VendorBuyMsgHandler extends AbstractClientMsgHandler {

    public VendorBuyMsgHandler() {
        super(VendorBuyMsg.class);
    }

    public static Item createItemForPlayer(PlayerCharacter pc, int templateID) {

        Item item = new Item(templateID);
        item.ownerID = pc.getObjectUUID();
        item.ownerType = mbEnums.OwnerType.PlayerCharacter;
        item.containerType = mbEnums.ItemContainerType.INVENTORY;

        try {
            item = DbManager.ItemQueries.PERSIST(item);
        } catch (Exception e) {
            Logger.error(e);
        }
        return item;
    }

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

        // Member variable declaration

        VendorBuyMsg vendorBuyMsg;

        // Member variable assignment

        vendorBuyMsg = (VendorBuyMsg) baseMsg;
        PlayerCharacter sourcePlayer = SessionManager.getPlayerCharacter(origin);
        Item vendorItem;

        if (sourcePlayer == null)
            return true;

        if (origin.buyLock.tryLock()) {

            try {
                CharacterItemManager itemMan = sourcePlayer.charItemManager;

                if (itemMan == null)
                    return true;

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

                if (npc == null)
                    return true;

                Item gold = itemMan.getGoldInventory();

                if (gold == null)
                    return true;

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

                if (sellInventory == null)
                    return true;

                if (vendorBuyMsg.getItemID() < 0) {
                    for (Item me : sellInventory) {

                        if (me.objectUUID == vendorBuyMsg.getItemID()) {

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

                            int cost = me.getValue();

                            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(mbEnums.ProtectionState.NPC))
                                building = null;

                            int buildingDeposit = cost - me.magicValue;

                            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;
                            }

                            vendorItem = createItemForPlayer(sourcePlayer, me.templateID);

                            if (vendorItem != null) {
                                //   me.transferEnchants(buy);
                                itemMan.addItemToInventory(vendorItem);
                                itemMan.updateInventory();
                                return true;
                            }
                        }
                    }
                    return true;
                }

                CharacterItemManager npcCim = npc.charItemManager;

                if (npcCim == null)
                    return true;

                vendorItem = Item.getFromCache(vendorBuyMsg.getItemID());

                if (vendorItem == null)
                    return true;

                //test room available for item

                if (!itemMan.hasRoomInventory(vendorItem.template.item_wt))
                    return true;

                int cost = vendorItem.template.item_value;

                if (vendorItem.flags.contains(mbEnums.ItemFlags.Identified) || vendorItem.isCustomValue())
                    cost = vendorItem.magicValue;

                float bargain = sourcePlayer.getBargain();

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

                if (profit < 1)
                    profit = 1;

                if (!vendorItem.isCustomValue())
                    cost *= profit;
                else
                    cost = vendorItem.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(mbEnums.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 (vendorItem != null) {
                    itemMan.buyFromNPC(vendorItem, npc);
                    itemMan.updateInventory();
                }
                return true;
            } catch (Exception e) {
                Logger.error(e);
            } finally {
                origin.buyLock.unlock();
            }
        }
        return true;
    }
}