#include "ShapedRecipie.h"

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

ShapedRecipieElement::ShapedRecipieElement()
    : Framework::UIMLElement()
{}

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

//! erstellt eine neue Drawable zu einem gegebenen xml Element
Framework::Drawable* ShapedRecipieElement::parseElement(
    Framework::XML::Element& element, Framework::UIMLContainer& generalFactory)
{
    int width = (int)element.getAttributeValue("width");
    int height = (int)element.getAttributeValue("height");
    ShapedRecipie* recipie = new ShapedRecipie(width, height);

    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 ShapedRecipieElement::updateElement(Framework::XML::Element& element,
    Framework::Drawable& z,
    Framework::UIMLContainer& generalFactory)
{
    return false;
}

//! wendet die layout parameter zu einer Drawable an
void ShapedRecipieElement::layout(Framework::XML::Element& element,
    Framework::Drawable& z,
    int pWidth,
    int pHeight,
    Framework::UIMLContainer& generalLayouter)
{
    UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter);
    int width = (int)element.getAttributeValue("width");
    int height = (int)element.getAttributeValue("height");
    int outputs
        = element.selectChildsByName("outputs").selectChildren().getSize();
    int outputCols = outputs / height;
    if (outputs % height != 0)
    {
        outputCols++;
    }
    if (outputCols == 0)
    {
        outputCols = 1;
    }
    z.setWidth(width * 60 + 50 + outputCols * 60 - 10);
    z.setHeight(height * 60 - 10);
    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);
            }
        });
}

ShapedRecipie::ShapedRecipie(int width, int height)
    : Framework::DrawableBackground(),
      width(width),
      height(height)
{
    setStyle(Framework::Drawable::Style::Allowed
             | Framework::Drawable::Style::Visible);
}

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

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

bool ShapedRecipie::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 ShapedRecipie::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;
    for (Drawable* ingredient : ingredients)
    {
        ingredient->setX(x);
        ingredient->setY(y);
        ingredient->render(rObj);
        x += 60;
        if (x >= width * 60)
        {
            x = 0;
            y += 60;
        }
    }
    rObj.fillRegion(width * 60, gr.y / 2 - 5, 25, 10, 0xFF52525E);
    rObj.drawTriangle(Framework::Point(width * 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;
    y = 0;
    for (Drawable* output : outputs)
    {
        output->setX(x);
        output->setY(y);
        output->render(rObj);
        y += 60;
    }
    rObj.releaseDrawOptions();
}

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