#include "ListView.h"

#include <Bild.h>
#include <Fenster.h>
#include <Liste.h>
#include <Schrift.h>
#include <TextFeld.h>
#include <XML.h>

#include "World.h"

ListViewElement::ListViewElement()
    : Framework::UIMLElement()
{}

bool ListViewElement::isApplicableFor(Framework::XML::Element& element)
{
    return element.getName().istGleich("listView");
}

Framework::Zeichnung* ListViewElement::parseElement(
    Framework::XML::Element& element, Framework::UIMLContainer& generalFactory)
{
    ListView* result = new ListView();
    result->list->setSchriftZ(dynamic_cast<Framework::Schrift*>(
        generalFactory.getFactory().initParam.schrift->getThis()));
    updateElement(element, *result, generalFactory);
    return result;
}

bool ListViewElement::updateElement(Framework::XML::Element& element,
    Framework::Zeichnung& z,
    Framework::UIMLContainer& generalFactory)
{
    ListView* view = dynamic_cast<ListView*>(&z);
    if (!view) return false;
    for (int index = 0; index < view->list->getEintragAnzahl(); index++)
    {
        if (!element.selectChildsByName("listItem")
                 .whereAttributeEquals("id", *view->ids.z(index))
                 .exists())
        {
            view->list->removeEintrag(index);
            view->ids.remove(index);
            index--;
        }
    }
    int childIndex = 0;
    for (Framework::XML::Element* zChild :
        element.selectChildsByName("listItem"))
    {
        int index = view->ids.findIndex([zChild](const Framework::Text* zId) {
            return zId->istGleich(zChild->getAttributeValue("id"));
        });
        if (index < 0)
        {
            Framework::Text id = zChild->getAttributeValue("id");
            view->ids.add(new Framework::Text(id));
            view->list->addEintrag(zChild->getText());
        }
        else
        {
            view->list->setEintrag(index, zChild->getText());
            view->list->setEintragPos(index, childIndex);
        }
        childIndex++;
    };
    for (int i = 0; i < view->list->getEintragAnzahl(); i++)
    {
        view->list->zEintrag(i)->setSchriftSize(20);
        view->list->zEintrag(i)->setSchriftFarbe(0XFFFFFFFF);
        view->list->zEintrag(i)->setRahmenFarbe(0xFF52525E);
    }
    int auswahl
        = element.selectChildsByAttribute("selected")
              .getFirstElement()
              .map<int>(
                  [](Framework::RCPointer<Framework::XML::Element> child) {
                      return child->zParent()->getChildIndex(child);
                  })
              .orElse(-1);
    view->list->setAuswahl(auswahl);
    view->lastSelection = auswahl;
    view->onSelected = element.getAttributeValue("onSelectMessage");
    return true;
}

void ListViewElement::layout(Framework::XML::Element& element,
    Framework::Zeichnung& z,
    int pWidth,
    int pHeight,
    Framework::UIMLContainer& generalLayouter)
{
    UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter);
    ListView* view = dynamic_cast<ListView*>(&z);
    if (view)
    {
        Framework::Text height = element.getAttributeValue("member-height");
        if (height.istGleich(""))
        {
            height = 30;
        }
        for (int i = 0; i < view->list->getEintragAnzahl(); i++)
        {
            view->list->zEintrag(i)->setHeight((int)height);
        }
        view->list->setSize(view->getInnenBreite(), view->getInnenHeight());
        if ((int)height * view->list->getEintragAnzahl() > view->getHeight())
        {
            view->list->addStyle(Framework::AuswahlListe::Style::VScroll);
            view->list->setVertikalKlickScroll((int)height);
            view->list->updateVScroll();
        }
        auto children = element.selectChildsByName("listItem");
        for (auto item : children)
        {
            auto elements
                = item->selectChildsByName("itemContent").selectChildren();
            int elementIndex = 0;
            for (auto element : elements)
            {
                generalLayouter.layout(*element,
                    *generalLayouter.zZeichnungById(
                        element->getAttributeValue("id")),
                    view->getBreite() - view->list->getBreite(),
                    view->getHeight(),
                    generalLayouter);
                elementIndex++;
            }
        }
    }
}

ListView::ListView()
    : Framework::Zeichnung(),
      list(new Framework::AuswahlListe())
{
    addStyle(Framework::Zeichnung::Style::Sichtbar
             | Framework::Zeichnung::Style::Erlaubt);
    setMausEreignis(Framework::_ret1ME);
    list->setStyle(Framework::AuswahlListe::Style::Normal);
    list->setMausEreignis(Framework::_ret1ME);
    list->setRahmenFarbe(0xFF52525E);
    list->setRahmenBreite(1);
    list->setALRBreite(2);
    list->setALRFarbe(0xFF0018FF);
    list->setAAFFarbe(0xA0337AB7);
    list->setAAFStrength(5);
    lastSelection = list->getAuswahl();
}

bool ListView::tick(double tickVal)
{
    rend |= list->tick(tickVal);
    int auswahl = list->getAuswahl();
    if (auswahl != lastSelection)
    {
        Framework::Text* dialogName
            = onSelected.getTeilText(0, onSelected.positionVon(";"));
        Framework::Text* messageId
            = onSelected.getTeilText(onSelected.positionVon(";") + 1);
        char msg[6];
        msg[0] = 0; // element message
        msg[1] = (char)(int)*messageId;
        *(int*)(msg + 2) = auswahl;
        World::INSTANCE->zClient()->uiRequest(*dialogName, msg, 6);
        dialogName->release();
        messageId->release();
        lastSelection = auswahl;
    }
    return Zeichnung::tick(tickVal);
}

void ListView::render(Framework::Bild& rObj)
{
    Zeichnung::render(rObj);
    if (rObj.setDrawOptions(pos, gr))
    {
        list->render(rObj);
        rObj.releaseDrawOptions();
    }
}

void ListView::doMausEreignis(Framework::MausEreignis& me, bool userRet)
{
    bool vera = me.verarbeitet;
    if (!userRet)
    {
        me.verarbeitet = 1;
    }
    list->doPublicMausEreignis(me);
    if (!userRet)
    {
        me.verarbeitet = vera;
    }
}
