#include "ItemBar.h"

#include <Bild.h>
#include <XML.h>

#include "Globals.h"

using namespace Framework;

ItemBarElement::ItemBarElement()
    : UIMLElement()
{}

//! pr�ft, ob dieses UIML Element f�r ein bestimmtes xml Element zust�ndig ist
bool ItemBarElement::isApplicableFor(Framework::XML::Element& element)
{
    return element.getName().istGleich("itemBar");
}

//! erstellt eine neue Zeichnung zu einem gegebenen xml Element
Framework::Zeichnung* ItemBarElement::parseElement(
    Framework::XML::Element& element, Framework::UIMLContainer& generalFactory)
{
    return new ItemBarView(element.getAttributeValue("id"),
        (int)element.getAttributeValue("rowSize"),
        (int)element.getAttributeValue("target"),
        element.getAttributeValue("slotNameFilter"));
}

bool ItemBarElement::updateElement(Framework::XML::Element& element,
    Framework::Zeichnung& z,
    Framework::UIMLContainer& generalFactory)
{
    return false;
}

//! wendet die layout parameter zu einer Zeichnung an
void ItemBarElement::layout(Framework::XML::Element& element,
    Framework::Zeichnung& z,
    int pWidth,
    int pHeight,
    Framework::UIMLContainer& generalLayouter)
{
    z.setHeight(52);
    z.setWidth(592);
    UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter);
}

ItemBarView::ItemBarView(Framework::Text id,
    int rowSize,
    int targetEntity,
    Framework::Text slotNameFilter)
    : ZeichnungHintergrund(),
      id(id),
      rowSize(rowSize),
      targetEntity(targetEntity),
      slotNameFilter(slotNameFilter),
      slots(0),
      leftHandPos(0)
{
    char* msg = new char[id.getLength() + slotNameFilter.getLength() + 3];
    msg[0] = 0;
    msg[1] = (char)id.getLength();
    memcpy(msg + 2, id.getText(), id.getLength());
    msg[2 + id.getLength()] = (char)slotNameFilter.getLength();
    memcpy(msg + 3 + id.getLength(),
        slotNameFilter.getText(),
        slotNameFilter.getLength());
    World::INSTANCE->zClient()->inventoryAPIRequest(
        targetEntity, msg, id.getLength() + slotNameFilter.getLength() + 3);
    World::INSTANCE->zClient()->sendPlayerAction("\x8", 1);
    delete[] msg;
}

ItemBarView::~ItemBarView()
{
    if (slots) slots->release();
    char* msg = new char[id.getLength() + 2];
    msg[0] = 1;
    msg[1] = (char)id.getLength();
    memcpy(msg + 2, id.getText(), id.getLength());
    World::INSTANCE->zClient()->inventoryAPIRequest(
        targetEntity, msg, id.getLength() + 2);
    delete[] msg;
}

void ItemBarView::api(char* message)
{
    switch (message[0])
    {
    case 0:
        // send inventory content
        {
            Array<SlotInfo>* slots = new Array<SlotInfo>();
            int count = *(int*)(++message);
            for (int i = 0; i < count; i++)
            {
                SlotInfo info;
                info.id = *(int*)(message += 4);
                info.itemCount = *(int*)(message += 4);
                if (info.itemCount > 0)
                {
                    info.hp = *(float*)(message += 4);
                    info.maxHp = *(float*)(message += 4);
                    info.durability = *(float*)(message += 4);
                    info.maxDurability = *(float*)(message += 4);
                    info.zItem = zItemType(*(int*)(message += 4))->zIcon();
                    char len = *(message += 4);
                    char* name = new char[len + 1];
                    memcpy(name, message += 1, len);
                    name[len] = 0;
                    info.name = name;
                    delete[] name;
                    message += len - 4;
                }
                slots->add(info);
            }
            window->zBildschirm()->postAction([this, slots]() {
                if (this->slots) this->slots->release();
                this->slots = slots;
            });
            break;
        }
    case 1: // set count of items
        {
            int id = *(int*)(message + 1);
            int count = *(int*)(message + 5);
            for (int i = 0; i < slots->getEintragAnzahl(); i++)
            {
                if (slots->get(i).id == id)
                {
                    SlotInfo info = slots->get(i);
                    info.itemCount = count;
                    slots->set(info, i);
                    break;
                }
            }
            break;
        }
    case 2: // add new stack
        {
            int id = *(int*)(message + 1);
            for (int i = 0; i < slots->getEintragAnzahl(); i++)
            {
                if (slots->get(i).id == id)
                {
                    SlotInfo info = slots->get(i);
                    info.itemCount = *(int*)(message + 5);
                    info.hp = *(float*)(message + 9);
                    info.maxHp = *(float*)(message + 13);
                    info.durability = *(float*)(message + 17);
                    info.maxDurability = *(float*)(message + 21);
                    info.zItem = zItemType(*(int*)(message + 25))->zIcon();
                    char len = *(message + 29);
                    char* name = new char[len + 1];
                    memcpy(name, message + 30, len);
                    name[len] = 0;
                    info.name = name;
                    delete[] name;
                    slots->set(info, i);
                    break;
                }
            }
            break;
        }
    case 3: // set selected slot
        {
            leftHandPos = *(int*)(message + 1);
            break;
        }
    }
}

void ItemBarView::render(Bild& rObj)
{
    ZeichnungHintergrund::render(rObj);
    if (!rObj.setDrawOptions(pos.x, pos.y, gr.x, gr.y)) return;
    if (slots)
    {
        int x = 0;
        int y = 0;
        int rowCount = 0;
        int index = 0;
        for (SlotInfo info : *slots)
        {
            info.render(x,
                y,
                rObj,
                index == leftHandPos, 0);
            x += 60;
            if (++rowCount >= rowSize)
            {
                y += 60;
                x = 0;
                rowCount = 0;
            }
            index++;
        }
    }
    rObj.releaseDrawOptions();
}