#include "UnshapedRecipie.h"

#include <Image.h>
#include <XML.h>

UnshapedRecipieElement::UnshapedRecipieElement()
    : Framework::UIMLElement()
{}

//! prüft, ob dieses UIML Element für ein bestimmtes xml Element zuständig
//! ist
bool UnshapedRecipieElement::isApplicableFor(Framework::XML::Element& element)
{
    return element.getName().isEqual("recipie")
        && element.getAttributeValue("type").isEqual("unshaped");
}

//! erstellt eine neue Drawable zu einem gegebenen xml Element
Framework::Drawable* UnshapedRecipieElement::parseElement(
    Framework::XML::Element& element, Framework::UIMLContainer& generalFactory)
{
    UnshapedRecipie* recipie = new UnshapedRecipie();

    element.selectChildsByName("ingredients")
        .selectChildren()
        .forEach([recipie, &generalFactory](Framework::XML::Element* zElement) {
            recipie->addIngredient(
                generalFactory.parseElement(*zElement, generalFactory));
        });

    element.selectChildsByName("outputs").selectChildren().forEach(
        [recipie, &generalFactory](Framework::XML::Element* zElement) {
            recipie->addOutput(
                generalFactory.parseElement(*zElement, generalFactory));
        });

    return recipie;
}

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

//! wendet die layout parameter zu einer Drawable an
void UnshapedRecipieElement::layout(Framework::XML::Element& element,
    Framework::Drawable& z,
    int pWidth,
    int pHeight,
    Framework::UIMLContainer& generalLayouter)
{
    UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter);
    element.selectChildren().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);
            }
        });
}

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

void UnshapedRecipie::addIngredient(Drawable* ingredient)
{
    ingredients.add(ingredient);
}

void UnshapedRecipie::addOutput(Drawable* output)
{
    outputs.add(output);
}

bool UnshapedRecipie::tick(double tickVal)
{
    bool ret = false;
    for (Drawable* ingredient : ingredients)
    {
        ret |= ingredient->tick(tickVal);
    }
    for (Drawable* output : outputs)
    {
        ret |= output->tick(tickVal);
    }
    return ret;
}

void UnshapedRecipie::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 x = 0;
    int y = 0;
    int width = MIN(3, ingredients.getEntryCount());
    for (Drawable* ingredient : ingredients)
    {
        ingredient->setX(x);
        ingredient->setY(y);
        ingredient->render(rObj);
        x += 60;
        if (x >= 3 * 60)
        {
            x = 0;
            y += 60;
        }
    }
    rObj.fillRegion(width * 60, gr.y / 2 - 5, 25, 10, 0xFF52525E);
    rObj.drawTriangle(Framework::Point(3 * 60 + 25, gr.y / 2 - 15),
        Framework::Point(width * 60 + 40, gr.y / 2),
        Framework::Point(width * 60 + 25, gr.y / 2 + 15),
        0xFF52525E);
    x = width * 60 + 50;
    int oldy = y;
    y = 0;
    for (Drawable* output : outputs)
    {
        output->setX(x);
        output->setY(y);
        output->render(rObj);
        y += 60;
    }
    int height = MAX(3, outputs.getEntryCount());
    if (getWidth() != width * 60 + 50 + 50 && getHeight() != height)
    {
        setSize(width * 60 + 50 + 50, MAX(oldy + 50, y + 50));
    }
    rObj.releaseDrawOptions();
}

void UnshapedRecipie::doMouseEvent(Framework::MouseEvent& me, bool userRet)
{
    for (Drawable* ingredient : ingredients)
    {
        ingredient->doPublicMouseEvent(me);
    }
    for (Drawable* output : outputs)
    {
        output->doPublicMouseEvent(me);
    }
}