#include "area_manager.hpp"

#include "../../util/math.hpp"

using namespace game::resource;
using namespace game::util;

namespace game::state::play
{
  int AreaManager::index_get(Entity& character)
  {
    auto& data = character.data;
    auto& schema = data.areaSchema;
    if (schema.areas.empty()) return -1;

    auto stages = data.stages_get();
    auto size = (int)stages.size();

    for (int i = 0; i < size; i++)
    {
      auto* stage = stages[size - i - 1];
      if (stage->areaID >= 0 && stage->areaID < (int)schema.areas.size()) return stage->areaID;
    }

    return 0;
  }

  game::resource::xml::Schema::AreaEntry* AreaManager::get(Entity& character)
  {
    auto index = index_get(character);
    if (index == -1) return nullptr;
    return &character.data.areaSchema.areas[index];
  }

  void AreaManager::set(Entity& character)
  {
    entities.clear();
    auto& areas = character.data.areaSchema.areas;
    entities.reserve(areas.size());

    for (auto& area : areas)
      entities.emplace_back(area.anm2.is_valid() ? Entity(area.anm2) : Entity{});
  }

  void AreaManager::update(Entity& character)
  {
    if (entities.size() != character.data.areaSchema.areas.size()) set(character);

    auto index = index_get(character);
    if (index == -1 || index >= (int)entities.size()) return;
    entities[index].update();
  }

  void AreaManager::render(Entity& character, Shader& textureShader, Shader& rectShader, Canvas& canvas)
  {
    if (entities.size() != character.data.areaSchema.areas.size()) set(character);

    auto index = index_get(character);
    if (index == -1) return;

    auto& area = character.data.areaSchema.areas[index];
    if (index < (int)entities.size() && area.anm2.is_valid())
    {
      entities[index].render(textureShader, rectShader, canvas);
      return;
    }

    if (!area.texture.is_valid()) return;

    auto worldModel = math::quad_model_get(area.texture.size);
    canvas.texture_render(textureShader, area.texture.id, worldModel);
  }
}
