#include "EntityType.h"

#include "Entity.h"
#include "Game.h"

EntityType::EntityType(int id, ModelInfo model)
    : ReferenceCounter(),
      id(id),
      model(model)
{
    StaticRegistry<EntityType>::INSTANCE.registerT(this, id);
}

void EntityType::loadSuperEntity(
    Entity* zEntity, Framework::StreamReader* zReader) const
{
    zEntity->loadInventory(zReader);
    zReader->lese((char*)&zEntity->id, 4);
    zReader->lese((char*)&zEntity->maxHP, 4);
    zReader->lese((char*)&zEntity->currentHP, 4);
    zReader->lese((char*)&zEntity->stamina, 4);
    zReader->lese((char*)&zEntity->maxStamina, 4);
    zReader->lese((char*)&zEntity->hunger, 4);
    zReader->lese((char*)&zEntity->maxHunger, 4);
    zReader->lese((char*)&zEntity->thirst, 4);
    zReader->lese((char*)&zEntity->maxThirst, 4);
    zReader->lese((char*)&zEntity->speed.x, 4);
    zReader->lese((char*)&zEntity->speed.y, 4);
    zReader->lese((char*)&zEntity->speed.z, 4);
    zReader->lese((char*)&zEntity->faceDir.x, 4);
    zReader->lese((char*)&zEntity->faceDir.y, 4);
    zReader->lese((char*)&zEntity->currentDimensionId, 4);
    zReader->lese((char*)&zEntity->location.x, 4);
    zReader->lese((char*)&zEntity->location.y, 4);
    zReader->lese((char*)&zEntity->location.z, 4);
    if (zEntity->target) delete zEntity->target;
    zEntity->target = ActionTarget::load(zReader);
    // load item skills
    zEntity->skills.leeren();
    int skillCount;
    zReader->lese((char*)&skillCount, 4);
    for (int i = 0; i < skillCount; i++)
    {
        int type;
        zReader->lese((char*)&type, 4);
        zEntity->skills.add(
            StaticRegistry<ItemType>::INSTANCE.zElement(type)->loadItemSkill(
                zReader));
    }
}

void EntityType::saveSuperEntity(
    Entity* zEntity, Framework::StreamWriter* zWriter) const
{
    zEntity->saveInventory(zWriter);
    zWriter->schreibe((char*)&zEntity->id, 4);
    zWriter->schreibe((char*)&zEntity->maxHP, 4);
    zWriter->schreibe((char*)&zEntity->currentHP, 4);
    zWriter->schreibe((char*)&zEntity->stamina, 4);
    zWriter->schreibe((char*)&zEntity->maxStamina, 4);
    zWriter->schreibe((char*)&zEntity->hunger, 4);
    zWriter->schreibe((char*)&zEntity->maxHunger, 4);
    zWriter->schreibe((char*)&zEntity->thirst, 4);
    zWriter->schreibe((char*)&zEntity->maxThirst, 4);
    zWriter->schreibe((char*)&zEntity->speed.x, 4);
    zWriter->schreibe((char*)&zEntity->speed.y, 4);
    zWriter->schreibe((char*)&zEntity->speed.z, 4);
    zWriter->schreibe((char*)&zEntity->faceDir.x, 4);
    zWriter->schreibe((char*)&zEntity->faceDir.y, 4);
    zWriter->schreibe((char*)&zEntity->currentDimensionId, 4);
    zWriter->schreibe((char*)&zEntity->location.x, 4);
    zWriter->schreibe((char*)&zEntity->location.y, 4);
    zWriter->schreibe((char*)&zEntity->location.z, 4);
    ActionTarget::save(zEntity->target, zWriter);
    // save item skills
    int skillCount = zEntity->skills.getEintragAnzahl();
    zWriter->schreibe((char*)&skillCount, 4);
    for (ItemSkill* skill : zEntity->skills)
    {
        int type = skill->zSkillType()->getId();
        zWriter->schreibe((char*)&type, 4);
        skill->zSkillType()->saveItemSkill(skill, zWriter);
    }
}

void EntityType::createSuperEntity(Entity* zEntity) const {}

Entity* EntityType::loadEntity(Framework::StreamReader* zReader) const
{
    Entity* entity = createEntity(Framework::Vec3<float>(0, 0, 0), 0, 0);
    loadSuperEntity(entity, zReader);
    return entity;
}

void EntityType::saveEntity(
    Entity* zEntity, Framework::StreamWriter* zWriter) const
{
    saveSuperEntity(zEntity, zWriter);
}

Entity* EntityType::createEntityAt(
    Framework::Vec3<float> position, int dimensionId) const
{
    Entity* entity = createEntity(
        position, dimensionId, Game::INSTANCE->getNextEntityId());
    createSuperEntity(entity);
    return entity;
}

int EntityType::getId() const
{
    return id;
}

const ModelInfo& EntityType::getModel() const
{
    return model;
}