#include "ListView.h"

#include <Font.h>
#include <Image.h>
#include <List.h>
#include <TextField.h>
#include <Window.h>
#include <XML.h>

#include "World.h"

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

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

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

bool ListViewElement::updateElement(Framework::XML::Element& element,
    Framework::Drawable& z,
    Framework::UIMLContainer& generalFactory)
{
    ListView* view = dynamic_cast<ListView*>(&z);
    if (!view) return false;
    for (int index = 0; index < view->list->getEntryCount(); index++)
    {
        if (!element.selectChildsByName("listItem")
                .whereAttributeEquals("id", *view->ids.z(index))
                .exists())
        {
            view->list->removeEntry(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->isEqual(zChild->getAttributeValue("id"));
        });
        if (index < 0)
        {
            Framework::Text id = zChild->getAttributeValue("id");
            view->ids.add(new Framework::Text(id));
            view->list->addEntry(zChild->getText());
        }
        else
        {
            view->list->setEntry(index, zChild->getText());
            view->list->setEntryPos(index, childIndex);
        }
        childIndex++;
    };
    for (int i = 0; i < view->list->getEntryCount(); i++)
    {
        view->list->zEntry(i)->setFontSize(20);
        view->list->zEntry(i)->setFontColor(0XFFFFFFFF);
        view->list->zEntry(i)->setBorderColor(0xFF52525E);
    }
    int auswahl
        = element.selectChildsByAttribute("selected")
              .getFirstElement()
              .map<int>(
                  [](Framework::RCPointer<Framework::XML::Element> child) {
                      return child->zParent()->getChildIndex(child);
                  })
              .orElse(-1);
    view->list->setSelection(auswahl);
    view->lastSelection = auswahl;
    view->onSelected = element.getAttributeValue("onSelectMessage");
    return true;
}

void ListViewElement::layout(Framework::XML::Element& element,
    Framework::Drawable& 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.isEqual(""))
        {
            height = 30;
        }
        for (int i = 0; i < view->list->getEntryCount(); i++)
        {
            view->list->zEntry(i)->setHeight((int)height);
        }
        view->list->setSize(view->getInnerWidth(), view->getInnerHeight());
        if ((int)height * view->list->getEntryCount() > view->getHeight())
        {
            view->list->addStyle(Framework::SelectionList::Style::VScroll);
            view->list->setVerticalClickScroll((int)height);
            view->list->updateVScroll();
        }
    }
}

ListView::ListView()
    : Framework::Drawable(),
      list(new Framework::SelectionList())
{
    addStyle(Framework::Drawable::Style::Visible
             | Framework::Drawable::Style::Allowed);
    setMouseEvent(Framework::_ret1ME);
    list->setStyle(Framework::SelectionList::Style::Normal);
    list->setMouseEvent(Framework::_ret1ME);
    list->setBorderColor(0xFF52525E);
    list->setBorderWidth(1);
    list->setSelectionBorderWidth(2);
    list->setSelectionBorderColor(0xFF0018FF);
    list->setSelectionAFColor(0xA0337AB7);
    list->setSelectionAFStrength(5);
    lastSelection = list->getSelection();
}

bool ListView::tick(double tickVal)
{
    rend |= list->tick(tickVal);
    int auswahl = list->getSelection();
    if (auswahl != lastSelection)
    {
        Framework::Text* dialogName
            = onSelected.getTeilText(0, onSelected.positionOf(";"));
        Framework::Text* messageId
            = onSelected.getTeilText(onSelected.positionOf(";") + 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 Drawable::tick(tickVal);
}

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

void ListView::doMouseEvent(Framework::MouseEvent& me, bool userRet)
{
    bool vera = me.processed;
    if (!userRet)
    {
        me.processed = 1;
    }
    list->doPublicMouseEvent(me);
    if (!userRet)
    {
        me.processed = vera;
    }
}
