#include "CraftingRecipies.h"

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

#include "Globals.h"
#include "RecipieGroup.h"

CraftingRecipiesElement::CraftingRecipiesElement()
    : Framework::UIMLElement()
{}

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

//! erstellt eine neue Zeichnung zu einem gegebenen xml Element
Framework::Zeichnung* CraftingRecipiesElement::parseElement(
    Framework::XML::Element& element, Framework::UIMLContainer& generalFactory)
{
    CraftingRecipies* recipies = new CraftingRecipies();
    element.selectChildsByName("craftingRecipieGroup")
        .forEach([recipies, &generalFactory](
                     Framework::XML::Element* zElement) {
            RecipieGroup* group = new RecipieGroup();
            group->setToolTip(zElement->getAttributeValue("name"));
            if (zElement->hasAttribute("itemIcon"))
            {
                int type = (int)zElement->getAttributeValue("itemIcon");
                group->setIcon(dynamic_cast<Framework::Bild*>(
                    zItemType(type)->zIcon()->getThis()));
            }
            zElement->selectChildren().forEach(
                [group, &generalFactory](Framework::XML::Element* zRecipie) {
                    group->addRecipie(
                        generalFactory.parseElement(*zRecipie, generalFactory));
                });
            recipies->addRecipieGroup(group);
        });
    return recipies;
}

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

//! wendet die layout parameter zu einer Zeichnung an
void CraftingRecipiesElement::layout(Framework::XML::Element& element,
    Framework::Zeichnung& z,
    int pWidth,
    int pHeight,
    Framework::UIMLContainer& generalLayouter)
{
    z.setSize(500, 500); // TODO: calculate size
    UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter);
    element.selectChildsByName("craftingRecipieGroup")
        .selectChildren()
        .forEach([&z, &generalLayouter](Framework::XML::Element* zElement) {
            Framework::Zeichnung* child = 0;
            if (zElement->hasAttribute("id"))
            {
                child = generalLayouter.zZeichnungById(
                    zElement->getAttributeValue("id"));
            }
            if (child)
            {
                generalLayouter.layout(*zElement,
                    *child,
                    z.getBreite(),
                    z.getHeight(),
                    generalLayouter);
            }
        });
}

CraftingRecipies::CraftingRecipies()
    : Framework::ZeichnungHintergrund()
{
    setStyle(Framework::Zeichnung::Style::Erlaubt
             | Framework::Zeichnung::Style::Sichtbar);

    previousPage = uiFactory.createKnopf(uiFactory.initParam);
    previousPage->setText("<");
    previousPage->setToolTipText("Previous Page",
        uiFactory.initParam.bildschirm,
        uiFactory.initParam.schrift);
    previousPage->setSize(20, 20);
    previousPage->setPosition(0, 35);
    previousPage->setStyle(
        Framework::Knopf::Style::Normal & ~Framework::Knopf::Style::Sichtbar);
    previousPage->setMausEreignis([this](void* p, void* z, MausEreignis me) {
        if (me.id == ME_RLinks)
        {
            RecipieGroup* previous = 0;
            for (RecipieGroup* group : recipieGroups)
            {
                if (group->hatStyle(Zeichnung::Style::Sichtbar) && previous)
                {
                    group->removeStyle(Zeichnung::Style::Sichtbar);
                    previous->addStyle(Zeichnung::Style::Sichtbar);
                }
                previous = group;
            }
        }
        return 1;
    });

    nextPage = uiFactory.createKnopf(uiFactory.initParam);
    nextPage->setText(">");
    nextPage->setToolTipText("Next Page",
        uiFactory.initParam.bildschirm,
        uiFactory.initParam.schrift);
    nextPage->setSize(20, 20);
    nextPage->setPosition(0, 35);
    nextPage->setStyle(
        Framework::Knopf::Style::Normal & ~Framework::Knopf::Style::Sichtbar);
    nextPage->setMausEreignis([this](void* p, void* z, MausEreignis me) {
        if (me.id == ME_RLinks)
        {
            bool next = 0;
            int index = 0;
            for (RecipieGroup* group : recipieGroups)
            {
                if (next)
                {
                    group->addStyle(Zeichnung::Style::Sichtbar);
                    break;
                }
                if (group->hatStyle(Zeichnung::Style::Sichtbar)
                    && recipieGroups.getEintragAnzahl() > index + 1)
                {
                    group->removeStyle(Zeichnung::Style::Sichtbar);
                    next = 1;
                }
                index++;
            }
        }
        return 1;
    });
}

void CraftingRecipies::addRecipieGroup(RecipieGroup* recipieGroup)
{
    recipieGroups.add(recipieGroup);
}

bool CraftingRecipies::tick(double tickVal)
{
    int visibleGroupIndex = -1;
    int index = 0;
    for (RecipieGroup* group : recipieGroups)
    {
        if (group->hatStyle(Zeichnung::Style::Sichtbar))
        {
            visibleGroupIndex = index;
        }
        rend |= group->tick(tickVal);
        index++;
    }
    nextPage->setX(getBreite() - 20);
    previousPage->setStyle(Knopf::Style::Sichtbar, visibleGroupIndex > 0);
    nextPage->setStyle(Knopf::Style::Sichtbar,
        visibleGroupIndex < recipieGroups.getEintragAnzahl() - 1);
    rend |= previousPage->tick(tickVal);
    rend |= nextPage->tick(tickVal);
    return ZeichnungHintergrund::tick(tickVal);
}

void CraftingRecipies::render(Framework::Bild& rObj)
{
    if (!hatStyle(Zeichnung::Style::Sichtbar)) return;
    ZeichnungHintergrund::render(rObj);
    if (!rObj.setDrawOptions(pos.x, pos.y, gr.x, gr.y)) return;
    int visibleGroupIndex = -1;
    int index = 0;
    for (RecipieGroup* group : recipieGroups)
    {
        if (group->hatStyle(Zeichnung::Style::Sichtbar))
        {
            visibleGroupIndex = index;
        }
        group->setPosition(0, 60);
        group->setSize(getBreite(), getHeight() - 60);
        group->render(rObj);
        index++;
    }
    int totalWidth = recipieGroups.getEintragAnzahl() * 31 + 1;
    int possibleDisplayedIcons = getBreite() / 31;
    int x = 0;
    if (possibleDisplayedIcons < recipieGroups.getEintragAnzahl()
        && visibleGroupIndex > possibleDisplayedIcons / 2)
    {
        x = (visibleGroupIndex - possibleDisplayedIcons / 2) * -31;
        if (recipieGroups.getEintragAnzahl() * 31 + 1 + x < getBreite())
        {
            x += getBreite() - (recipieGroups.getEintragAnzahl() * 31 + 1 + x);
        }
    }
    index = 0;
    for (RecipieGroup* group : recipieGroups)
    {
        rObj.fillRegion(x, 0, 30, 30, 0xFF000000);
        rObj.alphaBildSkall(x, 0, 30, 30, *group->zIcon());
        rObj.drawLinieH(x - 1, 0, 32, 0xFFFFFFFF);
        if (index != visibleGroupIndex)
        {
            rObj.drawLinieH(x - 1, 30, 32, 0xFFFFFFFF);
        }
        rObj.drawLinieV(x + 30, 0, 30, 0xFFFFFFFF);
    }
    Framework::TextRenderer tr(dynamic_cast<Framework::Schrift*>(
        uiFactory.initParam.schrift->getThis()));
    tr.setSchriftSize(12);
    Text t = Text("Machine page ") + Text(visibleGroupIndex + 1) + Text(" of ")
           + Text(recipieGroups.getEintragAnzahl());
    int tbr = tr.getTextBreite(t);
    tr.renderText(getBreite() / 2 - tbr / 2, 34, t, rObj, 0xFFFFFFFF);
    previousPage->render(rObj);
    nextPage->render(rObj);
    rObj.releaseDrawOptions();
}

void CraftingRecipies::doMausEreignis(Framework::MausEreignis& me, bool userRet)
{
    previousPage->doPublicMausEreignis(me);
    nextPage->doPublicMausEreignis(me);
    for (RecipieGroup* group : recipieGroups)
    {
        group->doPublicMausEreignis(me);
    }
}