#pragma once
#include <vector>
#include "image/image.hpp"
#include "game/game-data.hpp"
#include "a83/error.hpp"
//! элементы меню
class MenuItem {
public:
  MenuItem() = default;
  //! отображение пункта меню
  virtual void print(Font* pFont, Image& dst,
    int XPos = 0, int YPos = 0) const = 0;
  //! применить действие при нажатии
  virtual bool accept() { return true; }
  virtual void plus() {} ///< увеличить параметр
  virtual void sub() {} ///< уменьшить параметр
  virtual ~MenuItem() {}
private:
  nocopy(MenuItem);
};
//! меню с выбором строк и отображением настроек
class Menu {
protected:
  std::vector<MenuItem*> items = {}; ///< все пункты меню
  int XPos = 0, YPos = 0; ///< позиция отрисовки окна меню
  int XText = 0, YText = 0; ///< позиция отрисовки текста
  int XWnd = 0, YWnd = 0; ///< размер окна меню
  int selectSize = 0; ///< ширина выделяемой строки в буквах
  int select = 0; ///< текущий пункт меню
public:
  Menu() = default;
  nocopy(Menu);
  ~Menu() { vp_delete(items); }
  //! выбор пункта выше
  void up() {
    if (items.empty())
      return;
    --select;
    if (select < 0) select = items.size() - 1;
  }
  //! выбор пункта ниже
  void down() {
    if (items.empty())
      return;
    ++select;
    if (select >= int(items.size())) select = 0;
  }
  void param_plus() {
    if (items.empty())
      return;
    items[select]->plus();
  }
  void param_sub() {
    if (items.empty())
      return;
    items[select]->sub();
  }
  void add(MenuItem* pItem) {
    IFERROR(!pItem, "added null-item to menu");
    items.push_back(pItem);
  }
  /** настройка отображения меню
  
  x/yp - позиция окна
  x/yw - размер окна
  x/yt - позиция текста в окне
  ss - ширина (в кол-ве букв) выделяемого прямоуг-а */
  void init(int xp, int yp, int xw, int yw, int xt, int yt, int ss) {
    XPos = xp; YPos = yp;
    XWnd = xw; YWnd = yw;
    IFERROR((xw | yw) < 1 , "Menu.init -> bad window size");
    XText = xt; YText = yt;
    selectSize = ss;
    IFERROR(selectSize < 1 , "Menu.init -> bad selection size");
  }
  //! отображение всех пунктов меню
  void print(Image& pic) const {
    // Отрисовка фона меню. Чёрный прямоуг.
    pic.draw_rect_filled(XPos,YPos, XWnd,YWnd, Color(Color::BLACK));
    auto scape_y = Game::font->space_y;
    Game::font->space_y = 3;
    // отрисовка всех строк меню
    int strNum = 0;
    for (cnauto va: items) {
      auto x = XPos + XText;
      auto y = YPos + YText + strNum*(Game::font->space_y + Game::font->height);
      va->print(Game::font, pic, x, y);
      ++strNum;
    }
    // метка выбранной строки
    {
      auto sx = XPos + XText - 2;
      auto sy = YPos + YText - 2 + select * (Game::font->space_y + Game::font->height);
      auto mx = selectSize * (Game::font->space_x + Game::font->width) + 1;
      auto my = Game::font->space_y + Game::font->height;
      pic.draw_rect_filled_diff(sx,sy, mx,my, Color(Color::WHITE));
    }
    Game::font->space_y = scape_y;
  }
  //! применить выбор. Если 0, то будет выход из меню
  bool accept() const {
    if ( !items.empty())
      return items[select]->accept();
    return true;
  }
};
//! тип колбэк функции, выполняемой при выборе пункта меню
using void_callback = bool (*)();
#include "menu-bool.hpp"
#include "menu-difficulty.hpp"
#include "menu-flag.hpp"
#include "menu-resize.hpp"
#include "menu-text.hpp"
#include "menu-num.hpp"