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


package engine.net.client.msg;

import engine.Enum.ItemType;
import engine.exception.SerializationException;
import engine.net.AbstractConnection;
import engine.net.AbstractNetMsg;
import engine.net.ByteBufferReader;
import engine.net.ByteBufferWriter;
import engine.net.client.ClientConnection;
import engine.net.client.Protocol;
import engine.objects.*;

import java.util.ArrayList;

public class BuyFromNPCWindowMsg extends ClientNetMsg {

    private int unknown01;
    private int npcType;
    private int npcID;
    private float unknown02;
    private byte unknown03;
    private int unknown04;

    /**
     * This is the general purpose constructor
     */
    public BuyFromNPCWindowMsg(int unknown01, int npcType, int npcID,
                               float unknown02, byte unknown03, int unknown04) {
        super(Protocol.SHOPLIST);
        this.unknown01 = unknown01;
        this.npcType = npcType;
        this.npcID = npcID;
        this.unknown02 = unknown02;
        this.unknown03 = unknown03;
        this.unknown04 = unknown04;
    }

    /**
     * This constructor is used by NetMsgFactory. It attempts to deserialize the
     * ByteBuffer into a message. If a BufferUnderflow occurs (based on reading
     * past the limit) then this constructor Throws that Exception to the
     * caller.
     */
    public BuyFromNPCWindowMsg(AbstractConnection origin, ByteBufferReader reader) {
        super(Protocol.SHOPLIST, origin, reader);
    }

    /**
     * @see AbstractNetMsg#getPowerOfTwoBufferSize()
     */
    @Override
    protected int getPowerOfTwoBufferSize() {
        // Larger size for historically larger opcodes
        return (16);
    }

    /**
     * Deserializes the subclass specific items to the supplied NetMsgWriter.
     */
    @Override
    protected void _deserialize(ByteBufferReader reader) {
        unknown01 = reader.getInt();
        npcType = reader.getInt();
        npcID = reader.getInt();
        unknown02 = reader.getFloat();
        unknown03 = reader.get();
        unknown04 = reader.getInt();
    }

    /**
     * Serializes the subclass specific items from the supplied NetMsgReader.
     */
    @Override
    protected void _serialize(ByteBufferWriter writer)
            throws SerializationException {

        ClientConnection clientConnection = (ClientConnection) this.getOrigin();
        PlayerCharacter player = null;

        if (clientConnection != null)
            player = clientConnection.getPlayerCharacter();

        float sellPercent = 1;

        NPC npc = NPC.getFromCache(npcID);
        CharacterItemManager man = null;
        ArrayList<Item> inventory = null;
        ArrayList<MobEquipment> sellInventory = null;

        if (npc != null) {
            man = npc.getCharItemManager();
            Contract contract = npc.getContract();
            if (player != null) {
                float barget = player.getBargain();
                float profit = npc.getSellPercent(player) - barget;

                if (profit < 1)
                    profit = 1;

                sellPercent = 1 * profit;
            } else
                sellPercent = 1 * npc.getSellPercent();

            if (contract != null)
                sellInventory = contract.getSellInventory();
        }

        if (man != null)
            inventory = man.getInventory();

        writer.putInt(unknown01);
        writer.putInt(npcType);
        writer.putInt(npcID);

        writer.putFloat(sellPercent); //npc sell markup

        int size = 0;

        if (inventory != null)
            size += inventory.size();

        if (sellInventory != null)
            size += sellInventory.size();

        if (size == 0) {
            writer.put((byte) 0);
            writer.putInt(0);
            return;
        }

        writer.put((byte) 1);

        int ownerID = npc.getObjectUUID();
        int indexPosition = writer.position();
        writer.putInt(0); //placeholder for item cnt
        int total = 0;

        //add generic sell inventory from contract
        if (sellInventory != null) {

            for (MobEquipment mobEquipment : sellInventory) {
                try {
                    MobEquipment.serializeForVendor(mobEquipment, writer, sellPercent);
                } catch (SerializationException se) {
                    continue;
                }
                ++total;
            }
        }

        //add npc inventory
        if (inventory != null) {
            for (Item item : inventory) {
                if (item.getOwnerID() != ownerID)
                    continue;
                if (item.getItemBase().getType().equals(ItemType.GOLD)) {
                    if (item.getNumOfItems() == 0)
                        continue;
                }
                Item.serializeForClientMsgForVendorWithoutSlot(item, writer, sellPercent);
                ++total;
            }
        }
        writer.putIntAt(total, indexPosition);
    }

    /**
     * @return the unknown01
     */
    public int getUnknown01() {
        return unknown01;
    }

    /**
     * @param unknown01 the unknown01 to set
     */
    public void setUnknown01(int unknown01) {
        this.unknown01 = unknown01;
    }

    /**
     * @return the unknown02
     */
    public float getUnknown02() {
        return unknown02;
    }

    /**
     * @param unknown02 the unknown02 to set
     */
    public void setUnknown02(float unknown02) {
        this.unknown02 = unknown02;
    }

    /**
     * @return the unknown03
     */
    public byte getUnknown03() {
        return unknown03;
    }

    /**
     * @param unknown03 the unknown03 to set
     */
    public void setUnknown03(byte unknown03) {
        this.unknown03 = unknown03;
    }

    /**
     * @return the unknown04
     */
    public int getUnknown04() {
        return unknown04;
    }

    /**
     * @param unknown04 the unknown04 to set
     */
    public void setUnknown04(int unknown04) {
        this.unknown04 = unknown04;
    }

    /**
     * @return the npcType
     */
    public int getNpcType() {
        return npcType;
    }

    /**
     * @param npcType the npcType to set
     */
    public void setNpcType(int npcType) {
        this.npcType = npcType;
    }

    /**
     * @return the npcID
     */
    public int getNpcID() {
        return npcID;
    }

    /**
     * @param npcID the npcID to set
     */
    public void setNpcID(int npcID) {
        this.npcID = npcID;
    }

}