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

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

using namespace Dawn;

UIMenu::UIMenu(UICanvas *canvas, int32_t columns, int32_t rows) {
  assertNotNull(canvas);
  assertTrue(columns > 0);
  assertTrue(rows > 0);

  this->canvas = canvas;
  this->rows = rows;
  this->columns = columns;
  this->items = (UIMenuItem**)memoryFillWithZero(sizeof(UIMenuItem*)*columns*rows);
}

void UIMenu::setSize(int32_t cols, int32_t rows) {
  assertNotNull(this->items);
  assertTrue(columns > 0);
  assertTrue(rows > 0);
  assertTrue(columns != this->columns);
  assertTrue(rows != this->rows);

  memoryFree(this->items);
  this->items = (UIMenuItem**)memoryFillWithZero(sizeof(UIMenuItem*)*columns*rows);
}

UIMenuItem * UIMenu::getItem(int32_t x, int32_t y) {
  return this->items[x * this->columns + y];
}

void UIMenu::setPosition(int32_t x, int32_t y) {
  assertTrue(x >= 0 && x < this->columns);
  assertTrue(y >= 0 && y < this->rows);
  UIMenuItem *item;
  
  if(this->x != -1) {
    assertTrue(this->y != -1);
    item = this->getItem(this->x, this->y);
    if(item != nullptr) {
      item->onItemOff();
    }
  }

  this->eventCursorChange.invoke(this->x, this->y, x, y);

  this->x = x;
  this->y = y;
  item = this->getItem(x, y);
  if(item != nullptr && item->canBeOvered()) {
    item->onItemOver();
  }
} 

void UIMenu::moveRelative(int32_t x, int32_t y) {
  int32_t x2 = this->x + x;
  if(x2 < 0 || x2 >= this->columns) return;
  int32_t y2 = this->y + y;
  if(y2 < 0 || y2 >= this->rows) return;
  this->setPosition(x2, y2);
}

void UIMenu::setItem(int32_t x, int32_t y, UIMenuItem *item) {
  assertTrue(x >= 0);
  assertTrue(y >= 0);
  assertTrue(x < this->columns);
  assertTrue(y < this->rows);
  assertNotNull(item);
  assertNotNull(this->items);
  assertNull(this->getItem(x, y));

  this->items[x * this->columns + y] = item;
}

void UIMenu::onInactive() {
  this->eventMenuInactive.invoke();
}

void UIMenu::onActive() {
  this->eventMenuActive.invoke();
}

void UIMenu::onTick() {
  auto im = &this->canvas->getGame()->inputManager;

  if(im->isPressed(INPUT_BIND_ACCEPT)) {
    auto item = this->getItem(this->x, this->y);
    if(item != nullptr && item->canBeSelected()) {
      item->onItemSelected();
      return;
    }
  }
  
  if(im->isPressed(INPUT_BIND_NEGATIVE_Y)) {
    this->moveRelative(0, 1);
    return;
  }
  
  if(im->isPressed(INPUT_BIND_POSITIVE_Y)) {
    this->moveRelative(0, -1);
    return;
  }
  
  if(im->isPressed(INPUT_BIND_NEGATIVE_X)) {
    this->moveRelative(-1, 0);
    return;
  }

  if(im->isPressed(INPUT_BIND_POSITIVE_X)) {
    this->moveRelative(1, 0);
    return;
  }

  // TODO: Support more modes and holding buttons to scroll.
}

UIMenu::~UIMenu() {
  if(this->canvas->currentMenu == this) this->canvas->currentMenu = nullptr;
  memoryFree(this->items);
}