#include "ChatOptions.h"

#include <FileSystem.h>

#include "Globals.h"
#include "Initialization.h"

ChatOptions::ChatOptions()
    : Window()
{
    LTDBFile iconsDat;
    iconsDat.setFile(new Text("data/images/gui_icons.ltdb"));
    iconsDat.readData(0);

    setStyle(Window::Style::Allowed | Window::Style::Border
             | Window::Style::BodyBAlpha | Window::Style::Title
             | Window::Style::TitleBAlpha | Window::Style::Closable
             | Window::Style::ClosingBAlpha | Window::Style::ClosingBuffer
             | Window::Style::TitleBackground | Window::Style::BodyBackground
             | Window::Style::ClosingBackground | Window::Style::MEIgnoreInside
             | Window::Style::Movable | Style::ClosingBImage
             | Style::ClosingBuffer);
    removeStyle(Window::Style::Visible);
    setTitel("Chat options");
    setClosingMe([this](void* p, void* o, Framework::MouseEvent me) {
        if (me.id == Framework::ME_RLeft)
        {
            removeStyle(Window::Style::Visible);
        }
        return 1;
    });
    setSize(262, 367);
    setPosition(5, uiFactory.initParam.bildschirm->getBackBufferSize().y - 680);
    setMouseEvent(Framework::_ret1ME);
    setKeyboardEvent(Framework::_ret1TE);
    setBorderWidth(1);
    setBorderColor(0xFF52525E);
    setBodyBgColor(0xA0000000);
    setTBgColor(0xA0000000);
    setCloseBgColor(0xA0000000);
    setTFontZ(dynamic_cast<Font*>(uiFactory.initParam.font->getThis()));
    zTTextField()->setSize(0, 20);
    zTTextField()->addStyle(TextField::Style::Center);
    setCloseAfStrength(10);
    setCloseAfColor(0x5F9C0A0A);
    setCloseBgImageZ(iconsDat.load(0, new Text("close.png")));
    setCloseClickAfColor(0xFF9C0A0A);
    setCloseAfStrength(10);

    infoChannel = initCheckBox(5,
        5,
        250,
        20,
        Framework::CheckBox::Style::Normal
            & ~Framework::CheckBox::Style::Border,
        "Show info messages");
    infoChannel->setPostMouseEvent([this](void* p, void* o, MouseEvent me) {
        if (me.id == ME_RLeft)
        {
            char msg[13];
            msg[0] = infoChannel->hasStyle(CheckBox::Style::Selected) ? 1 : 2;
            msg[1] = 11;
            memcpy(msg + 2, "system:INFO", 11);
            World::INSTANCE->zClient()->chatAPIRequest(msg, 13);
        }
        return 1;
    });
    addMember(infoChannel);
    warningChannel = initCheckBox(5,
        30,
        250,
        20,
        Framework::CheckBox::Style::Normal
            & ~Framework::CheckBox::Style::Border,
        "Show warning messages");
    warningChannel->setPostMouseEvent([this](void* p, void* o, MouseEvent me) {
        if (me.id == ME_RLeft)
        {
            char msg[16];
            msg[0]
                = warningChannel->hasStyle(CheckBox::Style::Selected) ? 1 : 2;
            msg[1] = 14;
            memcpy(msg + 2, "system:WARNING", 14);
            World::INSTANCE->zClient()->chatAPIRequest(msg, 16);
        }
        return 1;
    });
    addMember(warningChannel);
    errorChannel = initCheckBox(5,
        55,
        250,
        20,
        Framework::CheckBox::Style::Normal
            & ~Framework::CheckBox::Style::Border,
        "Show error messages");
    errorChannel->setPostMouseEvent([this](void* p, void* o, MouseEvent me) {
        if (me.id == ME_RLeft)
        {
            char msg[14];
            msg[0] = errorChannel->hasStyle(CheckBox::Style::Selected) ? 1 : 2;
            msg[1] = 12;
            memcpy(msg + 2, "system:ERROR", 12);
            World::INSTANCE->zClient()->chatAPIRequest(msg, 14);
        }
        return 1;
    });
    addMember(errorChannel);
    TextField* blackListLabel = initTextField(5,
        90,
        250,
        20,
        Framework::TextField::Style::Text
            | Framework::TextField::Style::VCenter,
        "Ignored players:");
    addMember(blackListLabel);

    plus = iconsDat.load(0, new Text("plus.png"));
    trash = iconsDat.load(0, new Text("trash.png"));

    playerName = initTextField(
        5, 115, 225, 20, Framework::TextField::Style::TextField, "");
    playerName->setKeyboardEvent([this](void* o, void* p, KeyboardEvent te) {
        if (te.id == TE_Release && te.virtualKey == T_Enter)
        {
            if (playerName->zText()->getLength())
            {
                addIgnoredPlayer(playerName->zText()->getText(), 1);
                playerName->setText("");
            }
        }
        return 1;
    });
    addMember(playerName);
    addButton = initButton(235,
        115,
        20,
        20,
        Framework::Button::Style::BImage | Framework::Button::Style::BAlpha
            | Framework::Button::Style::Background,
        "");
    addButton->setAlphaFieldColor(0x5F337AB7);
    addButton->setToolTipText("Add player to list of ignored players",
        uiFactory.initParam.bildschirm,
        uiFactory.initParam.font);
    addButton->setBackgroundImageZ(dynamic_cast<Image*>(plus->getThis()));
    addButton->setMouseEvent([this](void* o, void* p, MouseEvent me) {
        if (me.id == ME_RLeft)
        {
            if (playerName->zText()->getLength())
            {
                addIgnoredPlayer(playerName->zText()->getText(), 1);
                playerName->setText("");
            }
        }
        return 1;
    });
    addMember(addButton);
    blackList = initObjTable(5,
        140,
        250,
        200,
        Framework::ObjTable::Style::normal
            | Framework::ObjTable::Style::VScroll,
        {
            {"Player", 212, 212, 212},
            {"Remove", 20,  20,  20 }
    },
        0);
    addMember(blackList);
}

ChatOptions::~ChatOptions()
{
    if (plus) plus->release();
    if (trash) trash->release();
}

void ChatOptions::init(char* data)
{
    infoChannel->removeStyle(CheckBox::Style::Selected);
    warningChannel->removeStyle(CheckBox::Style::Selected);
    errorChannel->removeStyle(CheckBox::Style::Selected);
    int len = *(int*)data;
    data += 4;
    for (int i = 0; i < len; i++)
    {
        char len = *(data++);
        data += len;
        if (len == 11)
        {
            infoChannel->addStyle(CheckBox::Style::Selected);
        }
        if (len == 12)
        {
            errorChannel->addStyle(CheckBox::Style::Selected);
        }
        if (len == 14)
        {
            warningChannel->addStyle(CheckBox::Style::Selected);
        }
    }
    uiFactory.initParam.bildschirm->postAction([this]() {
        while (blackList->getRowCount())
        {
            blackList->removeRow(0);
        }
    });
    len = *(int*)data;
    data += 4;
    for (int i = 0; i < len; i++)
    {
        char len = *(data++);
        char* name = new char[len + 1];
        memcpy(name, data, len);
        name[len] = 0;
        data += len;
        addIgnoredPlayer(name, 0);
        delete[] name;
    }
}

void ChatOptions::addIgnoredPlayer(Framework::Text playerName, bool msg)
{
    if (blackList->getRowNumber(playerName) >= 0) return;
    if (msg)
    {
        char* msg = new char[2 + playerName.getLength()];
        msg[0] = 3;
        msg[1] = (char)playerName.getLength();
        memcpy(msg + 2, playerName, playerName.getLength());
        World::INSTANCE->zClient()->chatAPIRequest(
            msg, 2 + playerName.getLength());
        delete[] msg;
    }
    uiFactory.initParam.bildschirm->postAction([this, playerName]() {
        if (blackList->getRowNumber(playerName) >= 0) return;
        blackList->addRow(playerName);
        blackList->setDrawableZ("Player",
            playerName,
            initTextField(0,
                0,
                0,
                0,
                TextField::Style::Text | TextField::Style::VCenter,
                playerName.getText()));
        Button* removeButton = initButton(0,
            0,
            0,
            0,
            Framework::Button::Style::BImage | Framework::Button::Style::BAlpha
                | Framework::Button::Style::Background,
            "");
        removeButton->removeStyle(Button::Style::Border);
        removeButton->setAlphaFieldColor(0x5F337AB7);
        removeButton->setToolTipText(
            "Remove player from list of ignored players",
            uiFactory.initParam.bildschirm,
            uiFactory.initParam.font);
        removeButton->setBackgroundImageZ(
            dynamic_cast<Image*>(trash->getThis()));
        removeButton->setMouseEvent(
            [this, playerName](void* o, void* p, MouseEvent me) {
                if (me.id == ME_RLeft)
                {
                    uiFactory.initParam.bildschirm->postAction(
                        [this, playerName]() {
                            char* msg = new char[2 + playerName.getLength()];
                            msg[0] = 4;
                            msg[1] = (char)playerName.getLength();
                            memcpy(msg + 2, playerName, playerName.getLength());
                            World::INSTANCE->zClient()->chatAPIRequest(
                                msg, 2 + playerName.getLength());
                            delete[] msg;
                            blackList->removeRow(playerName);
                        });
                }
                return 1;
            });
        blackList->setDrawableZ("Remove", playerName, removeButton);
    });
}