local ListBox = require "core.modules.menusystem.listbox"
local Widget  = require "core.modules.menusystem.widgets"

local MenuConstructor = Object:extend()
local CharacterMenu   = ListBox:extend()

local CharMenuWidget  = Widget.Text:extend()
local SubMenuWidget   = CharMenuWidget:extend()
local BackMenuWidget  = CharMenuWidget:extend()
local SkillWidget     = Widget.Text:extend()

local MENUPOS_X1, MENUPOS_X2, MENUPOS_Y = 32, 32, 110
local MENU_WIDTH, MENU_ITEM_HEIGHT = 112, 17
local MENU_ITEM_NUMBER = 6

function MenuConstructor:new( controller )
  self.controller = controller
end

function MenuConstructor:reconstruct(character)
  self.controller.menusystem:reset()
  self:build(character)

  self.controller.menusystem:switchMenu("BaseMenu")
end

function MenuConstructor:build(character)
  self:buildBaseMenu(character)
  self:buildSkillMenu(character)
  self:buildObjectMenu(character)
end

function MenuConstructor:buildBaseMenu(character)
  CharacterMenu(self.controller, "BaseMenu", MENUPOS_X1 - 16, MENUPOS_Y)
  CharMenuWidget(self.controller, "BaseMenu", "attack", "", character)
  SubMenuWidget(self.controller,  "BaseMenu", "skills", "SkillMenu", character)
  SubMenuWidget(self.controller,  "BaseMenu", "objects", "ObjectMenu", character)
  CharMenuWidget(self.controller, "BaseMenu", "defend", "", character)
  CharMenuWidget(self.controller, "BaseMenu", "flee", "", character)
  BackMenuWidget(self.controller, "BaseMenu", "back", character)

  self.controller.menusystem.menus["BaseMenu"]:setCancelWidget()
end

function MenuConstructor:set(currentCharacter)
  self:reconstruct(currentCharacter)
end

function MenuConstructor:buildSkillMenu(character)
  CharacterMenu(self.controller, "SkillMenu", MENUPOS_X1 - 16, MENUPOS_Y)
  local list = game.characters:getSkillList(character.charid)
  for k, skill in pairs(list) do
    SkillWidget(self.controller, "SkillMenu", skill.name, "", character)
  end
  SubMenuWidget(self.controller,  "SkillMenu", "back", "BaseMenu", character)

  self.controller.menusystem.menus["SkillMenu"]:setCancelWidget()
end

function MenuConstructor:buildObjectMenu(character)
  CharacterMenu(self.controller, "ObjectMenu", MENUPOS_X1 - 16, MENUPOS_Y)

  CharacterMenu(self.controller, "MedMenu",   MENUPOS_X1 - 16, MENUPOS_Y)
  CharacterMenu(self.controller, "RingMenu",  MENUPOS_X1 - 16, MENUPOS_Y)
  CharacterMenu(self.controller, "WispMenu",  MENUPOS_X1 - 16, MENUPOS_Y)
  CharacterMenu(self.controller, "OtherMenu", MENUPOS_X1 - 16, MENUPOS_Y)


  SubMenuWidget(self.controller,  "ObjectMenu", "heal",   "MedMenu",    character)
  SubMenuWidget(self.controller,  "ObjectMenu", "rings",  "RingMenu",   character)
  SubMenuWidget(self.controller,  "ObjectMenu", "wisps",  "WispMenu",   character)
  SubMenuWidget(self.controller,  "ObjectMenu", "other",  "OtherMenu",  character)

  SubMenuWidget(self.controller,  "ObjectMenu", "back", "BaseMenu",   character)
  SubMenuWidget(self.controller,  "MedMenu",    "back", "ObjectMenu", character)
  SubMenuWidget(self.controller,  "RingMenu",   "back", "ObjectMenu", character)
  SubMenuWidget(self.controller,  "WispMenu",   "back", "ObjectMenu", character)
  SubMenuWidget(self.controller,  "OtherMenu",  "back", "ObjectMenu", character)


  self.controller.menusystem.menus["ObjectMenu"]:setCancelWidget()

  self.controller.menusystem.menus["MedMenu"]:setCancelWidget()
  self.controller.menusystem.menus["RingMenu"]:setCancelWidget()
  self.controller.menusystem.menus["WispMenu"]:setCancelWidget()
  self.controller.menusystem.menus["OtherMenu"]:setCancelWidget()
end


function MenuConstructor:unset(  )
  self.isActive = false
end

-- CHARACTER_MENU
-- The actuals menus in the character menu

function CharacterMenu:new(scene, name, x, y)
  self.scene = scene
  local w, h = MENU_WIDTH, MENU_ITEM_NUMBER * MENU_ITEM_HEIGHT
  CharacterMenu.super.new(self, scene.menusystem, name, x, y, w, h, MENU_ITEM_NUMBER)
  self.cursorTexture = love.graphics.newImage("assets/gui/cursor-menulist.png")
  self.cursorTransition = 1
end

function CharacterMenu:update(dt)
  CharacterMenu.super.update(self, dt)

  local relativecursor = self.widget.selected - self.view.firstSlot

  local transition = self.cursorTransition - relativecursor

  if math.abs(transition) < 0.1 then
    self.cursorTransition = relativecursor
  else
    self.cursorTransition = (self.cursorTransition) + ((relativecursor) - (self.cursorTransition)) * dt*45
  end

end

function CharacterMenu:drawCursor()
  local addition = 17
  love.graphics.draw(self.cursorTexture, self.x + 4, self.y + (self.cursorTransition) * addition )
end

-- WIDGETS
-- All widgets used by the Characters menus

function CharMenuWidget:new(scene, menu_name, label1, label2, character)
  self.character = character
  self.menuname = menu_name
  self.scene    = scene
  self.actionType = label1

  local menu = scene.menusystem.menus[menu_name] or error("menu " ..menu_name .. " doesn't exist")
  local font = scene.assets.fonts["small"]
  CharMenuWidget.super.new(self, menu, font, core.lang:translate("battle", label1))
  self.label2 = label2 or ""
  self.isSelected = false
end

function CharMenuWidget:update(dt)
  CharMenuWidget.super.update(self, dt)
end

function CharMenuWidget:selectAction()
  self.isSelected = true
  if self.actionType == "attack" then
    self.scene.world:resetActiveGrid()
    self.scene.world:setEffectGrid(self.character.x + self.character.direction, self.character.y, "point", 1, 1)
  else
    self.scene.world:resetActiveGrid()
    self.scene.world:resetEffectGrid()
  end
end

function CharMenuWidget:drawCanvas()
  local h
  local asset = love.graphics.newImage("assets/gui/attacklist.png")
  love.graphics.draw(asset, 0, (self.height - 13) / 2)
  h = math.floor(self.height / 2) - (self.font:getHeight() / 2)
  love.graphics.setColor(0, 0, 0, .8)
  self.font:print(self.label, 17, h, "left")
  self.font:print(self.label2, self.width - 8, h, "right")
  utils.graphics.resetColor()
  self.font:print(self.label, 16, h, "left")
  self.font:print(self.label2, self.width - 9, h, "right")
end

function CharMenuWidget:action()
  self.scene.world:resetActiveGrid()
  self.scene.world:resetEffectGrid()
  self.character:receiveSignal(self.actionType)
  self.scene:flushKeys()
  self.scene.menusystem:reset()
end

-- Submenu Widget

function SubMenuWidget:new(scene, menu_name, label, newmenu, character)
  SubMenuWidget.super.new(self, scene, menu_name, label, "", character)
  self.newmenu = newmenu or "BaseMenu"
end

function SubMenuWidget:action()
  self.scene.menusystem:switchMenu(self.newmenu)
end

-- Back Widget

function BackMenuWidget:new(scene, menu_name, label, character)
  BackMenuWidget.super.new(self, scene, menu_name, "back", "", character)
end

function BackMenuWidget:action()
  self.scene.world:resetActiveGrid()
  self.scene.world:resetEffectGrid()
  self.character:receiveBackSignal()
  self.scene:flushKeys()
  self.scene.menusystem:reset()
end

-- Skill Widget

function SkillWidget:new(scene, menu_name, label1, label2, character)
  self.character = character
  self.menuname = menu_name
  self.scene    = scene
  self.actionType = label1

  local menu = scene.menusystem.menus[menu_name] or error("menu " ..menu_name .. " doesn't exist")
  local font = scene.assets.fonts["small"]

  self.skilldata = game.skills:getSkillData(self.actionType)

  CharMenuWidget.super.new(self, menu, font, core.lang:translate("skills", label1))

  if self.skilldata ~= nil then
    self.label2 = self.skilldata.cost or 0
    if self.label2 < 10 then
      self.label2 = "0" .. self.label2
    end
  else
    self.label2 = "n"
  end
end

function SkillWidget:selectAction()
  if self.skilldata ~= nil then
    if self.skilldata.target == nil then
      local x = self.character.x + self.skilldata.effectArea[1]
      local y = self.character.y + self.skilldata.effectArea[2]
      local shape = self.skilldata.effectArea[3]
      local size = self.skilldata.effectArea[4]
      local direction = self.character.direction
      self.scene.world:resetActiveGrid()
      self.scene.world:setEffectGrid(x, y, shape, size, direction)
    else
      local x = self.character.x + self.skilldata.target[1]
      local y = self.character.y + self.skilldata.target[2]
      local shape = self.skilldata.target[3]
      local size = self.skilldata.target[4]
      local direction = self.character.direction
      self.scene.world:setActiveGrid(x, y, shape, size, direction)
      self.scene.world:resetEffectGrid()
    end

  else
    self.scene.world:resetActiveGrid()
    self.scene.world:resetEffectGrid()
  end
end


function SkillWidget:drawCanvas()
  local h
  local asset = love.graphics.newImage("assets/gui/attacklist.png")
  love.graphics.draw(asset, 0, (self.height - 13) / 2)
  h = math.floor(self.height / 2) - (self.font:getHeight() / 2)
  love.graphics.setColor(0, 0, 0, .8)
  self.font:print(self.label, 17, h, "left")
  self.font:print(self.label2, self.width - 8, h, "right")
  utils.graphics.resetColor()
  self.font:print(self.label, 16, h, "left")
  self.font:print(self.label2, self.width - 9, h, "right")
end

function SkillWidget:action()
  self.scene.world:resetActiveGrid()
  self.scene.world:resetEffectGrid()

  if self.skilldata ~= nil then
    if self.skilldata.target == nil then
      self.character:useSkill(self.actionType, self.character.x, self.character.y)
    else
      local x         = self.character.x + self.skilldata.target[1]
      local y         = self.character.y + self.skilldata.target[2]
      local shape     = self.skilldata.target[3]
      local size      = self.skilldata.target[4]
      local direction = self.character.direction
      self.scene.world.cursor:setGridIgnoreActor(x, y, shape, size, direction)
      self.scene.world.cursor:set(self.character.x, self.character.y, "skill", self.actionType)
    end
  else
    core.debug:warning("cbs/menu", "skill " .. self.actionType .. " doesn't exist")
    self.character:receiveSignal("none")
  end
  self.scene:flushKeys()
  self.scene.menusystem:reset()
end

return MenuConstructor
