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

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

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

local MENUPOS_X1, MENUPOS_X2, MENUPOS_Y = 96, 32, 96
local MENU_WIDTH, MENU_ITEM_HEIGHT = 180, 17
local MENU_ITEM_NUMBER = 6

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

function MenuConstructor:reconstruct(character)
  core.debug:print("cbs/menu", "Reconstructing the menu")
  self.scene.menusystem:reset()
  self:build(character)

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

function MenuConstructor:build(character)
  core.debug:print("cbs/menu", "Building the menu")
  self:buildBaseMenu(character)
  self:buildSkillMenu(character)
  self:buildObjectMenu(character)

  self.scene.menusystem:setSoundFromSceneAssets("mBeep")
  self.scene.menusystem:activate()
end

function MenuConstructor:buildBaseMenu(character)
  CharacterMenu(self.scene, "BaseMenu", MENUPOS_X1 - 16, MENUPOS_Y)
  ActionWidget(character, "BaseMenu", "attack")
  SubMenuWidget(character,  "BaseMenu", "skills", "SkillMenu")
  SubMenuWidget(character,  "BaseMenu", "objects", "ObjectMenu")
  ActionWidget(character, "BaseMenu", "defend")
  ActionWidget(character, "BaseMenu", "flee")
end

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

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

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

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

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


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

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


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

  self.scene.menusystem.menus["MedMenu"]:setCancelWidget()
  self.scene.menusystem.menus["RingMenu"]:setCancelWidget()
  self.scene.menusystem.menus["WispMenu"]:setCancelWidget()
  self.scene.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 = 0
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
  local x = self.x + 4 + ((self.cursorTransition) * addition * 0.5)
  local y = self.y + ((self.cursorTransition) * addition)
  love.graphics.draw(self.cursorTexture, x, y)
end

function CharacterMenu:draw()
  self:updateView()
  local widgety = self.y
  local widgetx = self.x
  for i,v in ipairs(self.widget.list) do
    if (i >= self.view.firstSlot) and (i < self.view.firstSlot + self.view.slotNumber) then
      v:draw(widgetx, widgety, self.w, self.widget.h)
      if self.widget.selected == i and self:haveFocus() == true then
        v:drawSelected(widgetx, widgety, self.w, self.widget.h)
      else
        v:draw(widgetx, widgety, self.w, self.widget.h)
      end
      widgety = widgety + self.widget.h
      widgetx = widgetx + (self.widget.h/2)
    end
  end
end

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

-- Basic Battle Widget
-- The base used by all battle widgets

function BattleWidget:new(character, menu_name, label1, label2, translationdata)
  local menu = self:getControllers(character, menu_name)

  local translationdata = translationdata or "battle"
  local label1 = label1 or ""
  local label2 = label2 or ""
  label1 = core.lang:translate(translationdata, label1)

  local font = self.assets.fonts["small"]

  BattleWidget.super.new(self, menu, font, label1)

  self.label2 = label2
end

function BattleWidget:getControllers(character, menu_name)
  self.character = character or core.debug:error("cbs/widget", "character must not be nil")

  self.scene      = self.character.turnSystem.scene
  self.assets     = self.character.assets
  self.menusystem = self.scene.menusystem

  self.menuname   = menu_name

  local menu      = self.menusystem.menus[menu_name] or error("menu " ..menu_name .. " doesn't exist")

  return menu
end

-- Internal functions

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

function BattleWidget:selectAction()
  -- Rien de base, à voir ensuite comment je gère
end

function BattleWidget:drawCanvas()
  local h
  local asset   = love.graphics.newImage("assets/gui/attacklist.png")
  local sw, sh  = asset:getDimensions()
  local startAsset  = love.graphics.newQuad(0, 0, 16, sh, sw, sh)
  local midAsset    = love.graphics.newQuad(16, 0, 1, sh, sw, sh)
  local endAsset    = love.graphics.newQuad(sw-16, 0, 16, sh, sw, sh)

  local trueWidth = self.width - 32

  love.graphics.draw(asset, startAsset, 0, (self.height - 13) / 2)
  love.graphics.draw(asset, endAsset, trueWidth-16, (self.height - 13) / 2)

  local iterations = trueWidth-32

  for i=0,iterations do
    love.graphics.draw(asset, midAsset, 16+i, (self.height - 13) / 2)
  end


  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, trueWidth - 8, h, "right")
  utils.graphics.resetColor()
  self.font:print(self.label, 16, h, "left")
  self.font:print(self.label2, trueWidth - 9, h, "right")
end

function BattleWidget:action()
  self.scene:flushKeys()
  self.scene.menusystem:deactivate()

  self:sendCharacterData()
end

-- External functions

function BattleWidget:sendCharacterData()
  self.character:doNothing()
end

-- ActionWidget
-- The basic action widget

function ActionWidget:new(character, menu_name, action)
  self.actionType = action or ""
  ActionWidget.super.new(self, character, menu_name, action, "")
end

function ActionWidget:sendCharacterData()
  self.character:doBasicAction(self.actionType)
end

-- SubMenuWidget
-- A simple widget to change menu

function SubMenuWidget:new(character, menu_name, label, newmenu)
  local label2 = ""
  self.sfx = "mBack"
  if label ~= "back" then
    label2 = ">"
    self.sfx = "mBeep"
  end
  SubMenuWidget.super.new(self, character, menu_name, label, label2)
  self.newmenu = newmenu or "BaseMenu"
end

function SubMenuWidget:action()
  self.assets.sfx[self.sfx]:play()
  self.scene.menusystem:switchMenu(self.newmenu)
end

-- BackMenuWidget
-- Quit the menu

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

function BackMenuWidget:sendCharacterData()
  self.assets.sfx["mBack"]:play()
  self.character:receiveBackSignal()
end

-- SkillWidget
-- A widget to handle skills

function SkillWidget:new(character, menu_name, skill)
  self.skillname = skill
  local label2 = "00"

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

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

  SkillWidget.super.new(self, character, menu_name, self.skillname, "-" .. label2, "skills")
end

function SkillWidget:sendCharacterData()

  if self.skilldata ~= nil then
    self.assets.sfx["mSelect"]:play()
    self.character:useSkill(self.skillname)
  else
    core.debug:warning("cbs/menu", "skill " .. self.skillname .. " doesn't exist")
    self.character:doNothing()
    self.assets.sfx["mError"]:play()
  end

end

return MenuConstructor
