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

#pragma once
#include "event/Event.hpp"
#include "ui/UIComponent.hpp"
#include "util/memory.hpp"

namespace Dawn {
  class UIMenuItem {
    public:
      /**
       * Called when the item is selected (Accepted) on.
       */
      virtual void onItemSelected() = 0;

      /**
       * Called when either the mouse or the user controller input is removed
       * off this item.
       */
      virtual void onItemOver() = 0;
      
      /**
       * Called when either the mouth or the user controller input is put over
       * this item.
       */
      virtual void onItemOff() = 0;

      /**
       * Returns whether the UI item can be hovered overed or not.
       * @return Whether it can be overed or not.
       */
      virtual bool_t canBeOvered() = 0;

      /**
       * Returns whether or not the item can be selected or not.
       * @return Whether it can be selected or not.
       */
      virtual bool_t canBeSelected() = 0;
  };

  struct UIMenu {
    private:
      UICanvas *canvas;
      int32_t x = -1;
      int32_t y = -1;
      int32_t rows = 1;
      int32_t columns = 1;
      UIMenuItem **items = nullptr;

    protected:
      /** Invoked by UICanvas when this menu has been made inactive. */
      void onInactive();
      /** Invoked by UICanvas when this menu has been made active. */
      void onActive();
      /** Invoked by UICanvas every tick this menu is active. */
      void onTick();

    public:
      Event<> eventMenuActive;
      Event<> eventMenuInactive;
      Event<int32_t, int32_t, int32_t, int32_t> eventCursorChange;
      Event<UIMenuItem*> eventItemSelected;

      /**
       * Construct a new UI Menu Host.
       * 
       * @param canvas Canvas that this menu belongs to.
       * @param columns Iniitial size of the menu X axis.
       * @param rows Initial size of the menu Y axis.
       */
      UIMenu(UICanvas *canvas, int32_t columns, int32_t rows);

      /**
       * Sets the size of the UI Menu.
       * 
       * @param columns How many columns in the menu.
       * @param rows How many rows in the menu.
       */
      void setSize(int32_t columns, int32_t rows);

      /**
       * Returns the UI Item at the given position.
       * 
       * @param x X coordinate of the item to get.
       * @param y Y coordinate of the item to get.
       * @return The pointer to the menu item, or null if invalid.
       */
      UIMenuItem * getItem(int32_t x, int32_t y);

      /**
       * Sets the position of the cursor in the grid.
       * 
       * @param x X position of the cursor.
       * @param y Y position of the cursor.
       */
      void setPosition(int32_t x, int32_t y);

      /**
       * Move the cursor relative to the current position.
       * 
       * @param x X position to move relative.
       * @param y Y position to move relative.
       */
      void moveRelative(int32_t x, int32_t y);

      /**
       * Adds/Sets an item onto the menu.
       * 
       * @param x X coordinate to set the item.
       * @param y Y coordinate to set the item.
       * @param item Item to set.
       */
      void setItem(int32_t x, int32_t y, UIMenuItem *item);

      /**
       * Cleans up the menu items, doesn't free the children themselves.
       */
      ~UIMenu();

      friend class UICanvas;
  };
}