#include "ChatObserver.h"

#include <Datei.h>

#include "Chat.h"
#include "Game.h"
#include "Player.h"

ChatObserver::ChatObserver(int entityId)
    : ReferenceCounter(),
      entityId(entityId)
{
    Framework::Datei config;
    config.setDatei(Game::INSTANCE->getWorldDirectory() + "/chat/observer/"
                    + entityId + ".observer");
    if (config.existiert() && config.open(Framework::Datei::Style::lesen))
    {
        int count;
        config.lese((char*)&count, sizeof(int));
        for (int i = 0; i < count; i++)
        {
            char len;
            config.lese(&len, 1);
            char* buffer = new char[len + 1];
            config.lese(buffer, len);
            buffer[(int)len] = 0;
            channel.add(new Framework::Text(buffer));
        }
        config.lese((char*)&count, sizeof(int));
        for (int i = 0; i < count; i++)
        {
            char len;
            config.lese(&len, 1);
            char* buffer = new char[len + 1];
            config.lese(buffer, len);
            buffer[(int)len] = 0;
            ignoredPlayers.add(new Framework::Text(buffer));
        }
        config.close();
    }
    else
    {
        channel.add(new Framework::Text(Chat::CHANNEL_INFO));
        channel.add(new Framework::Text(Chat::CHANNEL_WARNING));
        channel.add(new Framework::Text(Chat::CHANNEL_ERROR));
    }
}

void ChatObserver::addChannel(Framework::Text channel)
{
    this->channel.add(new Framework::Text(channel));
}

void ChatObserver::removeChannel(Framework::Text channel)
{
    for (auto it = this->channel.begin(); it;)
    {
        if (it->istGleich(channel))
        {
            it.remove();
            continue;
        }
        it++;
    }
}

bool ChatObserver::isSubscribedTo(Framework::Text channel)
{
    if (channel.hatAt(0, Chat::getPlayerChannelName("")))
    {
        for (Framework::Text* ignored : ignoredPlayers)
        {
            if (channel.istGleich(Chat::getPlayerChannelName(*ignored)))
                return 0;
        }
        return 1;
    }
    else
    {
        for (Framework::Text* c : this->channel)
        {
            if (channel.istGleich(*c)) return 1;
        }
        return 0;
    }
}

void ChatObserver::addIgnoredPlayer(Framework::Text playerName)
{
    ignoredPlayers.add(new Framework::Text(playerName));
}

void ChatObserver::removeIgnoredPlayer(Framework::Text playerName)
{
    for (auto it = this->ignoredPlayers.begin(); it;)
    {
        if (it->istGleich(playerName))
        {
            it.remove();
            continue;
        }
        it++;
    }
}

int ChatObserver::getEntityId() const
{
    return entityId;
}

void ChatObserver::save() const
{
    Framework::Datei config;
    config.setDatei(Game::INSTANCE->getWorldDirectory() + "/chat/observer/"
                    + entityId + ".observer");
    config.erstellen();
    if (config.open(Framework::Datei::Style::schreiben))
    {
        writeTo(&config);
        config.close();
    }
}

void ChatObserver::writeTo(Framework::StreamWriter* zWriter) const
{
    int count = channel.getEintragAnzahl();
    zWriter->schreibe((char*)&count, sizeof(int));
    for (Framework::Text* c : channel)
    {
        char len = (char)c->getLength();
        zWriter->schreibe(&len, 1);
        zWriter->schreibe(c->getText(), len);
    }
    count = ignoredPlayers.getEintragAnzahl();
    zWriter->schreibe((char*)&count, sizeof(int));
    for (Framework::Text* ignored : ignoredPlayers)
    {
        char len = (char)ignored->getLength();
        zWriter->schreibe(&len, 1);
        zWriter->schreibe(ignored->getText(), len);
    }
}

bool ChatObserver::isValid() const
{
    return Game::INSTANCE->zEntity(entityId) != 0;
}

Framework::Text ChatObserver::getPlayerName() const
{
    Entity* zEntity = Game::INSTANCE->zEntity(entityId);
    if (zEntity)
    {
        Player* p = dynamic_cast<Player*>(zEntity);
        if (p)
        {
            return p->getName();
        }
    }
    return "";
}