#include "StatusBars.h"

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

#include "Globals.h"

StatusBarsElement::StatusBarsElement()
    : UIMLElement()
{}

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

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

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

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

StatusBarsView::StatusBarsView(Framework::Text id, int targetEntity)
    : ZeichnungHintergrund(),
      id(id),
      targetEntity(targetEntity)
{
    setStyle(ZeichnungHintergrund::Style::Sichtbar
             | ZeichnungHintergrund::Style::Rahmen
             | ZeichnungHintergrund::Style::Hintergrund
             | ZeichnungHintergrund::Style::HAlpha);
    setRahmenFarbe(0xA052525E);
    setHintergrundFarbe(0xA0222222);
    setRahmenBreite(2);
    Framework::LTDBDatei file;
    file.setDatei(new Framework::Text("data/images/gui_icons.ltdb"));
    file.leseDaten(0);
    healthIcon = file.laden(0, new Framework::Text("health.png"));
    energyIcon = file.laden(0, new Framework::Text("energy.png"));
    hungerIcon = file.laden(0, new Framework::Text("food.png"));
    thirstIcon = file.laden(0, new Framework::Text("water.png"));
    health = 0.f;
    hunger = 0.f;
    thirst = 0.f;
    energy = 0.f;
    tr.setSchriftZ(
        dynamic_cast<Schrift*>(uiFactory.initParam.schrift->getThis()));
    tr.setSchriftSize(12);
    char* msg = new char[id.getLength() + 2];
    msg[0] = 0; // request status bar state
    msg[1] = (char)id.getLength();
    memcpy(msg + 2, id.getText(), id.getLength());
    World::INSTANCE->zClient()->entityAPIRequest(
        targetEntity, msg, id.getLength() + 2);
    delete[] msg;
}

StatusBarsView::~StatusBarsView()
{
    char* msg = new char[id.getLength() + 2];
    msg[0] = 1; // remove status bar observer
    msg[1] = (char)id.getLength();
    memcpy(msg + 2, id.getText(), id.getLength());
    World::INSTANCE->zClient()->entityAPIRequest(
        targetEntity, msg, id.getLength() + 2);
    delete[] msg;
    healthIcon->release();
    energyIcon->release();
    hungerIcon->release();
    thirstIcon->release();
}

void StatusBarsView::api(char* message)
{
    switch (message[0])
    {
    case 0: // initialisation
        {
            float maxHealth = *(float*)(message + 1);
            float health = *(float*)(message + 5);
            float maxStamina = *(float*)(message + 9);
            float stamina = *(float*)(message + 13);
            float maxHunger = *(float*)(message + 17);
            float hunger = *(float*)(message + 21);
            float maxThirst = *(float*)(message + 25);
            float thirst = *(float*)(message + 29);
            this->health = health / maxHealth;
            this->energy = stamina / maxStamina;
            this->hunger = hunger / maxHunger;
            this->thirst = thirst / maxThirst;
            lockZeichnung();
            healthText = (int)ceil(health);
            energyText = (int)ceil(stamina);
            hungerText = (int)ceil(hunger);
            thirstText = (int)ceil(thirst);
            unlockZeichnung();
            break;
        }
    case 1: // update health
        {
            float maxHealth = *(float*)(message + 1);
            float health = *(float*)(message + 5);
            this->health = health / maxHealth;
            lockZeichnung();
            healthText = (int)ceil(health);
            unlockZeichnung();
            break;
        }
    case 2: // update stamina
        {
            float maxStamina = *(float*)(message + 1);
            float stamina = *(float*)(message + 5);
            this->energy = stamina / maxStamina;
            lockZeichnung();
            energyText = (int)ceil(stamina);
            unlockZeichnung();
            break;
        }
    case 3: // update hunger
        {
            float maxHunger = *(float*)(message + 1);
            float hunger = *(float*)(message + 5);
            this->hunger = hunger / maxHunger;
            lockZeichnung();
            hungerText = (int)ceil(hunger);
            unlockZeichnung();
            break;
        }
    case 4: // update thirst
        {
            float maxThirst = *(float*)(message + 1);
            float thirst = *(float*)(message + 5);
            this->thirst = thirst / maxThirst;
            lockZeichnung();
            thirstText = (int)ceil(thirst);
            unlockZeichnung();
            break;
        }
    }
    setRender();
}

void StatusBarsView::render(Framework::Bild& rObj)
{
    ZeichnungHintergrund::render(rObj);
    if (!rObj.setDrawOptions(pos.x + getRahmenBreite(),
            pos.y + getRahmenBreite(),
            gr.x - getRahmenBreite() * 2,
            gr.y - getRahmenBreite() * 2))
        return;
    rObj.alphaBild(0, 0, 20, 20, *healthIcon);
    rObj.alphaBild(gr.x - getRahmenBreite() * 2 - 20, 10, 20, 20, *energyIcon);
    rObj.alphaBild(0, 20, 20, 20, *hungerIcon);
    rObj.alphaBild(gr.x - getRahmenBreite() * 2 - 20, 30, 20, 20, *thirstIcon);
    lockZeichnung();
    tr.renderText(25, 4, healthText, rObj, 0xFFFFFFFF);
    tr.renderText(25, 24, hungerText, rObj, 0xFFFFFFFF);
    int leftTxtBr
        = MAX(tr.getTextBreite(healthText), tr.getTextBreite(hungerText));
    int rightTxtBr
        = MAX(tr.getTextBreite(energyText), tr.getTextBreite(thirstText));
    tr.renderText(gr.x - getRahmenBreite() * 2 - 25 - rightTxtBr,
        14,
        energyText,
        rObj,
        0xFFFFFFFF);
    tr.renderText(gr.x - getRahmenBreite() * 2 - 25 - rightTxtBr,
        34,
        thirstText,
        rObj,
        0xFFFFFFFF);
    unlockZeichnung();
    int leftWidth = gr.x - 62 - leftTxtBr - getRahmenBreite() * 2 - rightTxtBr;
    if (leftWidth > 0)
    {
        rObj.drawLinieVAlpha(30 + leftTxtBr, 0, gr.y, 0xA052525E);
        rObj.drawLinieVAlpha(gr.x - getRahmenBreite() * 2 - 31 - rightTxtBr,
            0,
            gr.y,
            0xA052525E);

        for (int i = 0; i <= 6; i++)
            rObj.drawLinieHAlpha(30 + leftTxtBr + 1, i, leftWidth, 0xA052525E);
        for (int i = 13; i <= 16; i++)
            rObj.drawLinieHAlpha(30 + leftTxtBr + 1, i, leftWidth, 0xA052525E);
        for (int i = 23; i <= 22; i++)
            rObj.drawLinieHAlpha(30 + leftTxtBr + 1, i, leftWidth, 0xA052525E);
        for (int i = 23; i <= 32; i++)
            rObj.drawLinieHAlpha(30 + leftTxtBr + 1, i, leftWidth, 0xA052525E);
        for (int i = 33; i <= 42; i++)
            rObj.drawLinieHAlpha(30 + leftTxtBr + 1, i, leftWidth, 0xA052525E);
        for (int i = 43; i <= 49; i++)
            rObj.drawLinieHAlpha(30 + leftTxtBr + 1, i, leftWidth, 0xA052525E);
        for (int i = 0; i < 6; i++)
        {
            rObj.drawLinieH(30 + leftTxtBr + 1,
                7 + i,
                (int)((float)leftWidth * health),
                0xFFB9180C);
            rObj.drawLinieHAlpha(
                30 + leftTxtBr + 1 + (int)((float)leftWidth * health),
                7 + i,
                leftWidth - (int)((float)leftWidth * health),
                0xA052525E);
            rObj.drawLinieH(30 + leftTxtBr + 1,
                17 + i,
                (int)((float)leftWidth * energy),
                0xFFF0C800);
            rObj.drawLinieHAlpha(
                30 + leftTxtBr + 1 + (int)((float)leftWidth * energy),
                17 + i,
                leftWidth - (int)((float)leftWidth * energy),
                0xA052525E);
            rObj.drawLinieH(30 + leftTxtBr + 1,
                27 + i,
                (int)((float)leftWidth * hunger),
                0xFF008300);
            rObj.drawLinieHAlpha(
                30 + leftTxtBr + 1 + (int)((float)leftWidth * hunger),
                27 + i,
                leftWidth - (int)((float)leftWidth * hunger),
                0xA052525E);
            rObj.drawLinieH(30 + leftTxtBr + 1,
                37 + i,
                (int)((float)leftWidth * thirst),
                0xFF0018FF);
            rObj.drawLinieHAlpha(
                30 + leftTxtBr + 1 + (int)((float)leftWidth * thirst),
                37 + i,
                leftWidth - (int)((float)leftWidth * thirst),
                0xA052525E);
        }
    }
    rObj.releaseDrawOptions();
}
