// Copyright (c) 2023 Dominic Masters
// 
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT

#include "UILabel.hpp"
#include "game/DawnGame.hpp"

using namespace Dawn;

UILabel::UILabel(SceneItem *item) :
  UIComponentRenderable(item),
  text(""),
  fontSize(10.0f),
  font(&item->scene->game->renderManager.defaultFont),
  maxWidth(UI_LABEL_MAX_WIDTH_ALIGN),
  startQuad(0),
  quadCount(-1)
{
}

bool_t UILabel::hasText() {
  return (
    this->font != nullptr &&
    this->font->isReady() &&
    ((std::string)this->text).size() > 0
  );
}

void UILabel::updateMesh() {
  if(!this->needsRebuffering) return;
  if(!this->hasText()) return;

  float_t width = this->maxWidth;
  assertTrue(
    width == UI_LABEL_MAX_WIDTH_NONE ||
    width == UI_LABEL_MAX_WIDTH_ALIGN ||
    width > 0
  );

  if(width == UI_LABEL_MAX_WIDTH_ALIGN) {
    auto dimensional = this->getParentDimensional();
    auto align = (glm::vec4)this->alignment;
    float_t x;
    UIComponent::calculateDimensions(
      this->alignX,
      this->alignUnitLeft,
      this->alignUnitRight,
      &x,
      &width,
      dimensional->getWidth(),
      0,
      glm::vec2(align[0], align[2])
    );
  }
  
  this->font->buffer(
    text,
    fontSize,
    width,
    &this->mesh,
    &this->measure
  );

  this->needsRebuffering = false;

  this->eventFontRebuffered.invoke();
}

std::vector<struct ShaderPassItem> UILabel::getUIRenderPasses() {
  if(!this->hasText()) return {};
  this->updateMesh();
  
  struct ShaderPassItem item;
  auto shader = getGame()->renderManager.uiShader;
  item.shader = shader;
  item.colorValues[shader->paramColor] = textColor;
  item.parameterBuffers[shader->bufferUiCanvas] = &getCanvas()->shaderBuffer;
  item.matrixValues[shader->paramModel] = this->transform->getWorldTransform();
  item.textureSlots[0] = this->font->getTexture();
  item.textureValues[shader->paramTexture] = 0;
  item.start = this->startQuad * QUAD_INDICE_COUNT;
  item.count = this->quadCount == -1 ? -1 : this->quadCount * QUAD_INDICE_COUNT;
  item.w = this->transform->getWorldPosition().z;
  item.renderFlags = RENDER_MANAGER_RENDER_FLAG_BLEND;
  item.mesh = &mesh;
  
  return { item };
}

float_t UILabel::getContentWidth() {
  if(!this->hasText()) return 0;
  this->updateMesh();
  return this->measure.getWidth();
}

float_t UILabel::getContentHeight() {
  if(!this->hasText()) return 0;
  this->updateMesh();
  return this->measure.getHeight();
}

void UILabel::onStart() {
  UIComponent::onStart();

  useEffect([&]{
    alignmentNeedsUpdating = true;
  }, { &fontSize, &font, &text, &maxWidth, &startQuad, &quadCount });

  useEffect([&]{
    eventTextChanged.invoke();
  }, text);

  useEffect([&]{
    needsRebuffering = true;
  }, alignmentNeedsUpdating);

  useEvent([&]{
    needsRebuffering = true;
  }, eventAlignmentUpdated);
}