#include "CraftingRecipies.h"

#include <Image.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().isEqual("craftingRecipies");
}

//! erstellt eine neue Drawable zu einem gegebenen xml Element
Framework::Drawable* 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::Image*>(
                    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::Drawable& z,
    Framework::UIMLContainer& generalFactory)
{
    return false;
}

//! wendet die layout parameter zu einer Drawable an
void CraftingRecipiesElement::layout(Framework::XML::Element& element,
    Framework::Drawable& 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::Drawable* child = 0;
            if (zElement->hasAttribute("id"))
            {
                child = generalLayouter.zDrawableById(
                    zElement->getAttributeValue("id"));
            }
            if (child)
            {
                generalLayouter.layout(*zElement,
                    *child,
                    z.getWidth(),
                    z.getHeight(),
                    generalLayouter);
            }
        });
}

CraftingRecipies::CraftingRecipies()
    : Framework::DrawableBackground()
{
    setStyle(Framework::Drawable::Style::Allowed
             | Framework::Drawable::Style::Visible);

    previousPage = uiFactory.createButton(uiFactory.initParam);
    previousPage->setText("<");
    previousPage->setToolTipText("Previous Page",
        uiFactory.initParam.bildschirm,
        uiFactory.initParam.font);
    previousPage->setSize(20, 20);
    previousPage->setPosition(0, 35);
    previousPage->setStyle(
        Framework::Button::Style::Normal & ~Framework::Button::Style::Visible);
    previousPage->setMouseEvent([this](void* p, void* z, MouseEvent me) {
        if (me.id == ME_RLeft)
        {
            RecipieGroup* previous = 0;
            for (RecipieGroup* group : recipieGroups)
            {
                if (group->hasStyle(Drawable::Style::Visible) && previous)
                {
                    group->removeStyle(Drawable::Style::Visible);
                    previous->addStyle(Drawable::Style::Visible);
                }
                previous = group;
            }
        }
        return 1;
    });

    nextPage = uiFactory.createButton(uiFactory.initParam);
    nextPage->setText(">");
    nextPage->setToolTipText(
        "Next Page", uiFactory.initParam.bildschirm, uiFactory.initParam.font);
    nextPage->setSize(20, 20);
    nextPage->setPosition(0, 35);
    nextPage->setStyle(
        Framework::Button::Style::Normal & ~Framework::Button::Style::Visible);
    nextPage->setMouseEvent([this](void* p, void* z, MouseEvent me) {
        if (me.id == ME_RLeft)
        {
            bool next = 0;
            int index = 0;
            for (RecipieGroup* group : recipieGroups)
            {
                if (next)
                {
                    group->addStyle(Drawable::Style::Visible);
                    break;
                }
                if (group->hasStyle(Drawable::Style::Visible)
                    && recipieGroups.getEntryCount() > index + 1)
                {
                    group->removeStyle(Drawable::Style::Visible);
                    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->hasStyle(Drawable::Style::Visible))
        {
            visibleGroupIndex = index;
        }
        rend |= group->tick(tickVal);
        index++;
    }
    nextPage->setX(getWidth() - 20);
    previousPage->setStyle(Button::Style::Visible, visibleGroupIndex > 0);
    nextPage->setStyle(Button::Style::Visible,
        visibleGroupIndex < recipieGroups.getEntryCount() - 1);
    rend |= previousPage->tick(tickVal);
    rend |= nextPage->tick(tickVal);
    return DrawableBackground::tick(tickVal);
}

void CraftingRecipies::render(Framework::Image& rObj)
{
    if (!hasStyle(Drawable::Style::Visible)) return;
    DrawableBackground::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->hasStyle(Drawable::Style::Visible))
        {
            visibleGroupIndex = index;
        }
        group->setPosition(0, 60);
        group->setSize(getWidth(), getHeight() - 60);
        group->render(rObj);
        index++;
    }
    int totalWidth = recipieGroups.getEntryCount() * 31 + 1;
    int possibleDisplayedIcons = getWidth() / 31;
    int x = 0;
    if (possibleDisplayedIcons < recipieGroups.getEntryCount()
        && visibleGroupIndex > possibleDisplayedIcons / 2)
    {
        x = (visibleGroupIndex - possibleDisplayedIcons / 2) * -31;
        if (recipieGroups.getEntryCount() * 31 + 1 + x < getWidth())
        {
            x += getWidth() - (recipieGroups.getEntryCount() * 31 + 1 + x);
        }
    }
    index = 0;
    for (RecipieGroup* group : recipieGroups)
    {
        rObj.fillRegion(x, 0, 30, 30, 0xFF000000);
        if (group->zIcon())
        {
            rObj.alphaImageScaled(x, 0, 30, 30, *group->zIcon());
        }
        else
        {
            // TODO: any item icon
        }
        rObj.drawLineH(x - 1, 0, 32, 0xFFFFFFFF);
        if (index != visibleGroupIndex)
        {
            rObj.drawLineH(x - 1, 30, 32, 0xFFFFFFFF);
        }
        rObj.drawLineV(x + 30, 0, 30, 0xFFFFFFFF);
    }
    Framework::TextRenderer tr(
        dynamic_cast<Framework::Font*>(uiFactory.initParam.font->getThis()));
    tr.setFontSize(12);
    Text t = Text("Machine page ") + Text(visibleGroupIndex + 1) + Text(" of ")
           + Text(recipieGroups.getEntryCount());
    int tbr = tr.getTextWidth(t);
    tr.renderText(getWidth() / 2 - tbr / 2, 34, t, rObj, 0xFFFFFFFF);
    previousPage->render(rObj);
    nextPage->render(rObj);
    rObj.releaseDrawOptions();
}

void CraftingRecipies::doMouseEvent(Framework::MouseEvent& me, bool userRet)
{
    previousPage->doPublicMouseEvent(me);
    nextPage->doPublicMouseEvent(me);
    for (RecipieGroup* group : recipieGroups)
    {
        group->doPublicMouseEvent(me);
    }
}