local classlib = require("core.class")
local consts = require("ui.consts")
local fsm = require("ui.fsm")
local reticleConsts = require("ui.reticleConsts")
local util = require("ui.util")
local UI = game.UI
local Player = game.Player
local EMISSIVE_TINT = "cst_EmissiveTint"
local LAYER = "LayerX"
local Reticle = classlib.Class("Reticle", fsm.UIState)
local RetOff = Reticle:StateClass("RetOff", fsm.UIState)
local RetOn = Reticle:StateClass("RetOn", fsm.UIState)
local reticle = Reticle.New("reticle", {RetOff, RetOn})
function Reticle:Enter()
  self:Goto("RetOn")
end
function Reticle:EVT_TURN_ON_RETICLE()
  self:Goto("RetOn")
end
function Reticle:EVT_TURN_OFF_RETICLE()
  self:Goto("RetOff")
end
Reticle.EVT_Restart = Reticle.Enter
Reticle.EVT_GAME_START = Reticle.Enter
function RetOff:Enter()
end
function RetOff:Exit()
end
function RetOn:Setup()
  self.globalState = reticleConsts.GS_NON_COMBAT
  self.aimState = false
  self.currReticleState = reticleConsts.RS_ON_NO_AIM
  self.currMinigameAmount = 0
  util.SetScreenspacePos("reticle", 0, 0.125)
end
function RetOn:Enter()
  self.isHoldingBreath = false
  UI.ForceHighMips("ret_aim_minigame_default", true)
  UI.ForceHighMips("ret_aim_minigame_hold_breath", true)
  UI.ForceHighMips("ret_hitValid_minigame_hold_breath", true)
  UI.Anim("ret_aim_minigame_default", consts.AS_Forward, "", 0, 0)
  UI.Anim("ret_aim_minigame_hold_breath", consts.AS_Forward, "", 0, 0)
  UI.Anim("ret_hitValid_minigame_hold_breath", consts.AS_Forward, "", 0, 0)
  self:HideAllReticles()
end
function RetOn:UpdateReticleTints(state)
  for gameObjName, material in pairs(reticleConsts.RETICLE_MATERIALS) do
    local gameObj = util.GetUiObjByName(gameObjName)
    local color_index = reticleConsts.COLOR_INDICES[gameObjName]
    local color = reticleConsts.RETICLE_TINTS[state][color_index]
    util.SetGameObjectColor(gameObj, color, material, LAYER, EMISSIVE_TINT)
  end
end
function RetOn:Exit()
  self.isHoldingBreath = false
  self:HideAllReticles()
end
function RetOn:HideAllReticles()
  util.Hide(table.unpack(reticleConsts.ALL_RETICLES))
end
function RetOn:ReticleStateToString(reticleState)
  return reticleConsts.stateNames[reticleState]
end
function RetOn:ShowAimReticle(reticleState)
  if self.globalState ~= nil and reticleConsts.aimingReticles[self.globalState] ~= nil then
    local reticleGOName = reticleConsts.aimingReticles[self.globalState][reticleState]
    local playerCreature = game.Player.FindPlayer()
    local reticleData = playerCreature:GetReticleState()
    local mechanic = reticleData.Mechanic
    local mechanicInRange = reticleData.IsMechanicInRange
    local mechanicAvailable = reticleData.IsMechanicAvailable
    local hitCreature = reticleData.HitType == "Creature"
    local isInRange = reticleData.IsInRange
    local reticleTintState = reticleConsts.STATES.NONE
    if hitCreature and isInRange then
      reticleTintState = reticleConsts.STATES.CREATURE
    end
    if mechanic ~= reticleConsts.STATES.NONE and mechanicInRange then
      util.Show(reticleConsts.RETICLE_OUTER, reticleConsts.BACKDROP)
    else
      util.Hide(reticleConsts.RETICLE_OUTER, reticleConsts.BACKDROP)
    end
    if mechanic ~= reticleConsts.STATES.NONE and mechanicAvailable then
      reticleTintState = mechanic
    end
    local backdrop = util.GetUiObjByName(reticleConsts.BACKDROP)
    if mechanic ~= reticleConsts.STATES.NONE and mechanicAvailable and mechanicInRange then
      backdrop:SetMaterialSwap(mechanic)
    else
      backdrop:SetMaterialSwap(reticleConsts.STATES.NONE)
    end
    self:UpdateReticleTints(reticleTintState)
    if reticleGOName ~= nil then
      util.Show(table.unpack(reticleGOName))
    end
  end
end
function RetOn:UpdateReticle(reticleState)
  self:HideAllReticles()
  if reticleState ~= reticleConsts.RS_OFF or game.GetReticleAlwaysOn() then
    if self.aimState == true or reticleState == reticleConsts.RS_LOCKED_ON then
      self:ShowAimReticle(reticleState)
    else
      local reticleGOName
      if game.GetReticleAlwaysOn() then
        reticleGOName = reticleConsts.alwaysOnReticles[self.globalState]
      else
        reticleGOName = reticleConsts.notAimingReticles[self.globalState]
      end
      if reticleGOName ~= nil then
        util.Show(table.unpack(reticleGOName))
      end
    end
  end
  self.currReticleState = reticleState
end
function RetOn:GetCombatGlobalState()
  local combatState = reticleConsts.GS_NON_COMBAT
  if util.IsInCombat() == true then
    combatState = reticleConsts.GS_COMBAT
  end
  return combatState
end
function RetOn:AnimateMinigameReticle(amount)
  if amount >= self.currMinigameAmount then
    UI.Anim("ret_aim_minigame_hold_breath", consts.AS_Forward, "", 1, self.currMinigameAmount, amount)
    UI.Anim("ret_hitValid_minigame_hold_breath", consts.AS_Forward, "", 1, self.currMinigameAmount, amount)
  else
    UI.Anim("ret_aim_minigame_hold_breath", consts.AS_Reverse, "", 1, self.currMinigameAmount, amount)
    UI.Anim("ret_hitValid_minigame_hold_breath", consts.AS_Reverse, "", 1, self.currMinigameAmount, amount)
  end
  self.currMinigameAmount = amount
end
function RetOn:EVT_UI_RETICLE()
  if self.globalState ~= reticleConsts.GS_MINIGAME then
    local state = UI.GetEventArgInt(1)
    if self.globalState ~= reticleConsts.GS_RAGE then
      self.globalState = self:GetCombatGlobalState()
    end
    self:UpdateReticle(state)
  end
end
function RetOn:EVT_MINIGAME_START()
  self.globalState = reticleConsts.GS_MINIGAME
  self:UpdateReticle(consts.currReticleState)
  util.SetScreenspacePos("reticle", 0.25, 0)
end
function RetOn:EVT_MINIGAME_END()
  self.globalState = self:GetCombatGlobalState()
  self.aimState = false
  self:UpdateReticle(self.currReticleState)
  util.SetScreenspacePos("reticle", 0, 0.125)
end
function RetOn:EVT_MINIGAME_HOLD_BREATH_START()
  if self.globalState == reticleConsts.GS_MINIGAME then
    self.aimState = true
    self:UpdateReticle(self.currReticleState)
    self:AnimateMinigameReticle(0)
  end
end
function RetOn:EVT_MINIGAME_HOLD_BREATH_END()
  if self.globalState == reticleConsts.GS_MINIGAME then
    self.aimState = false
    self:UpdateReticle(self.currReticleState)
  end
end
function RetOn:EVT_MINIGAME_HOLD_BREATH(amount)
  self:AnimateMinigameReticle(amount)
end
function RetOn:EVT_MINIGAME_HOLD_BREATH_INVALID_TARGET()
  if self.globalState == reticleConsts.GS_MINIGAME and self.aimState == true then
    self:UpdateReticle(reticleConsts.RS_IN_RANGE)
  end
end
function RetOn:EVT_MINIGAME_HOLD_BREATH_VALID_TARGET()
  if self.globalState == reticleConsts.GS_MINIGAME and self.aimState == true then
    self:UpdateReticle(reticleConsts.RS_HAS_TARGET)
  end
end
function RetOn:EVT_AIM_START()
  self.aimState = true
  self:UpdateReticle(self.currReticleState)
end
function RetOn:EVT_AIM_END()
  self.aimState = false
  self:UpdateReticle(self.currReticleState)
end
function Reticle:OnSaveCheckpoint(tab)
end
function Reticle:OnRestoreCheckpoint(tab)
end
