local classlib = require("core.class")
local tablex = require("core.tablex")
local consts = require("ui.consts")
local hooks = require("ui.hooks")
local slider = require("ui.slider")
local tutorialConsts = require("ui.tutorialConsts")
local tutorialUtil = require("ui.tutorialUtil")
local util = require("ui.util")
local Audio = game.Audio
local UI = game.UI
local SliderHoldFill = classlib.Class("SliderHoldFill", slider.Slider)
local PressEventHandler = function(sliderHoldFill)
  if sliderHoldFill._inputDisabledFunction == nil or not sliderHoldFill._inputDisabledFunction() then
    sliderHoldFill:StartHold()
  end
end
local ReleaseEventHandler = function(sliderHoldFill)
  if sliderHoldFill._inputDisabledFunction == nil or not sliderHoldFill._inputDisabledFunction() then
    sliderHoldFill:StartRelease()
  end
end
local AnimEndEventHandler = function(sliderHoldFill)
  local objNameHash = UI.GetEventArgStringHash(1)
  local percentComplete = UI.GetEventArgFloat(3) / 100
  local goSender = UI.GetEventSenderGameObject()
  sliderHoldFill:AnimEnd(goSender, objNameHash, percentComplete)
end
function SliderHoldFill:init(state, args)
  assert(state ~= nil, "Attempted to create new SliderHoldFill without state!")
  assert(args ~= nil, "Attempted to create new SliderHoldFill without args!")
  self._state = state
  self._active = false
  self._isHolding = false
  self._isFull = false
  self._isEmpty = true
  self._incrementEvents = nil
  self._decrementEvents = nil
  self._holdStartSound = args.HoldStartSound
  self._holdSound = args.HoldSound
  self._stopSound = args.StopSound
  self._successSound = args.SuccessSound
  self._name = util.GetValueWithDefault(args.Name, "SliderHoldFill_NotNamed")
  self._stopWhenFull = util.GetValueWithDefault(args.StopWhenFull, false)
  self._incAnimRate = util.GetValueWithDefault(args.IncAnimRate, 1)
  self._decAnimRate = util.GetValueWithDefault(args.DecAnimRate, 0.75)
  self._pressEvent = util.GetValueWithDefault(args.PressEvent, "EVT_Advance_Press")
  self._releaseEvent = util.GetValueWithDefault(args.ReleaseEvent, "EVT_Advance_Release")
  self._inputDisabledFunction = util.GetValueWithDefault(args.InputDisabled, nil)
  if self._goSlider ~= nil then
    self._goFlourish = self._goSlider:FindSingleGOByName("Flourish")
    if self._goFlourish then
      self._goFlourish:Show()
    end
  end
  self._hookTokens = {}
  self._OnComplete = args.OnComplete
  self._OnReset = args.OnReset
  self:Setup()
  self:SetText("")
end
function SliderHoldFill:Activate(show)
  if not self._active then
    if self._pressEvent ~= nil then
      util.InstallEventHooks(hooks, self, {
        self._pressEvent
      }, function(slider)
        tutorialUtil.HandleEvent(slider, {
          self._pressEvent
        }, PressEventHandler)
      end)
    end
    if self._releaseEvent ~= nil then
      util.InstallEventHooks(hooks, self, {
        self._releaseEvent
      }, function(slider)
        tutorialUtil.HandleEvent(slider, {
          self._releaseEvent
        }, ReleaseEventHandler)
      end)
    end
    util.InstallEventHooks(hooks, self, {
      "EVT_Anim_End"
    }, AnimEndEventHandler)
    self._active = true
    if show == true then
      self:Show()
    end
  end
end
function SliderHoldFill:Deactivate(hide)
  if self._active then
    self._active = false
    if self._pressEvent ~= nil then
      util.UninstallEventHooks(hooks, self, {
        self._pressEvent
      })
    end
    if self._releaseEvent ~= nil then
      util.UninstallEventHooks(hooks, self, {
        self._releaseEvent
      })
    end
    util.UninstallEventHooks(hooks, self, {
      "EVT_Anim_End"
    })
    tablex.Clear(self._hookTokens)
    if self._isFull == true then
      self:Reset()
    elseif self._isHolding == true then
      self:StartRelease()
    end
  end
  if hide == true then
    self:Hide()
    self:OnSliderParentHide()
  end
end
function SliderHoldFill:Reset()
  if self._isHolding == true and not util.IsStringNilOrEmpty(self._holdSound) then
    Audio.StopSound(self._holdSound)
  end
  if self._isEmpty == false and not util.IsStringNilOrEmpty(self._stopSound) then
    Audio.StopSound(self._stopSound)
  end
  self._isHolding = false
  self._isFull = false
  self._isEmpty = true
  self:AnimFill(consts.AS_Forward, "", 0, 0)
  if self._OnReset ~= nil then
    self._OnReset()
  end
end
function SliderHoldFill:ShouldStopBecauseFull()
  return self._isFull == true and self._stopWhenFull == true
end
function SliderHoldFill:StartHold()
  if self._isHolding == false and not self:ShouldStopBecauseFull() then
    self._isHolding = true
    if self._isEmpty == true then
      self:AnimFill(consts.AS_Forward, "", 0, 0.1)
      self._isEmpty = false
    end
    if not util.IsStringNilOrEmpty(self._stopSound) then
      Audio.StopSound(self._stopSound)
    end
    if not util.IsStringNilOrEmpty(self._holdSound) then
      Audio.PlaySliderSyncedSound(self._holdSound, self._goSliderChild.AnimPercent, self._incAnimRate, self._goSliderChild.AnimLengthTime)
    end
    if not util.IsStringNilOrEmpty(self._holdStartSound) then
      Audio.PlaySound(self._holdStartSound)
    end
    self:AnimFill(bit32.bor(consts.AS_Forward_NoReset, consts.AS_EndEvent), "", self._incAnimRate)
  end
end
function SliderHoldFill:StartRelease()
  if self._isHolding == true and not self:ShouldStopBecauseFull() then
    self._isHolding = false
    if not util.IsStringNilOrEmpty(self._holdSound) then
      Audio.StopSound(self._holdSound)
    end
    if not util.IsStringNilOrEmpty(self._stopSound) then
      Audio.PlaySliderSyncedSound(self._stopSound, 1 - self._goSliderChild.AnimPercent, self._decAnimRate, self._goSliderChild.AnimLengthTime)
    end
    self:AnimFill(bit32.bor(consts.AS_Reverse_NoReset, consts.AS_EndEvent), "", self._decAnimRate)
  end
end
function SliderHoldFill:SetOnComplete(newOnCompleteFunction)
  if newOnCompleteFunction ~= nil and type(newOnCompleteFunction) == "function" then
    self._OnComplete = newOnCompleteFunction
  end
end
function SliderHoldFill:ShouldHandleAnimEndEvent(goSender, objNameHash)
  local shouldHandle = false
  if self._goSlider ~= nil then
    shouldHandle = self._goSliderChild == goSender
  end
  return shouldHandle
end
function SliderHoldFill:AnimEnd(goSender, objNameHash, percentComplete)
  if self:ShouldHandleAnimEndEvent(goSender, objNameHash) == true then
    if self._isFull == false and self._isHolding == true and 0.99 <= percentComplete then
      self._isFull = true
      if not util.IsStringNilOrEmpty(self._successSound) then
        Audio.PlaySound(self._successSound)
      end
      if self._OnComplete ~= nil then
        self._OnComplete()
        tutorialUtil.CheckConditionMet(self._state, tutorialConsts.EVENT_TYPE_SLIDER_ON_COMPLETE, self._name, nil)
      end
      if self._goFlourish then
        local animName = ""
        local animRate = 1
        local frameMax = 30
        local animFrame_Start = 0
        local animFrame_End = 30
        local animPos_Start = animFrame_Start / frameMax
        local animPos_End = animFrame_End / frameMax
        UI.Anim(self._goFlourish, consts.AS_Forward, animName, animRate, animPos_Start, animPos_End)
      end
    elseif percentComplete <= 0.01 then
      self._isEmpty = true
      if not util.IsStringNilOrEmpty(self._stopSound) then
        Audio.StopSound(self._stopSound)
      end
    end
  end
end
function SliderHoldFill:PlayUnavailableSound()
  if self:get_active() == false then
    Audio.PlaySound("SND_UX_Menu_Tick_Fail")
  end
end
function SliderHoldFill:SetSounds(holdSound, stopSound, successSound)
  if self._holdSound ~= nil then
    Audio.StopSound(self._holdSound)
  end
  self._holdSound = holdSound
  if self._stopSound ~= nil then
    Audio.StopSound(self._stopSound)
  end
  self._stopSound = stopSound
  if self._successSound ~= nil then
    Audio.StopSound(self._successSound)
  end
  self._successSound = successSound
end
function SliderHoldFill:OnSliderParentHide()
  if self._isHolding == true and not util.IsStringNilOrEmpty(self._holdSound) then
    Audio.StopSound(self._holdSound)
  end
  if self._isEmpty == false and not util.IsStringNilOrEmpty(self._stopSound) then
    Audio.StopSound(self._stopSound)
  end
end
return {SliderHoldFill = SliderHoldFill}
