local classlib = require("core.class")
local tablex = require("core.tablex")
local colors = require("ui.colors")
local consts = require("ui.consts")
local meter = require("ui.meter")
local util = require("ui.util")
local GetTextHandle = util.GetTextHandle
local SetText = game.UI.SetText
local UI = game.UI
local MeterPreview = classlib.Class("MeterPreview", meter.Meter)
function MeterPreview:init(state, args)
  assert(state ~= nil, "Attempted to create new MeterPreview without state!")
  assert(args ~= nil, "Attempted to create new MeterPreview without args!")
  self._state = state
  self._active = false
  self._goMeter = nil
  self._goMeterChild = nil
  self._goFill = nil
  self._goFillChild = nil
  self._goPreviewFill = nil
  self._goPreviewFillChild = nil
  self._previewFillObjectName = args.PreviewFillObjectName
  self._previewFillInstanceChildName = util.GetValueWithDefault(args.PreviewFillInstanceChildName, "meter")
  self._previewColor = util.GetValueWithDefault(args.PreviewColor, colors.ATTRIBUTE_METER_DEFAULT)
  self._betterColor = util.GetValueWithDefault(args.BetterColor, colors.ATTRIBUTE_METER_BETTER)
  self._worseColor = util.GetValueWithDefault(args.WorseColor, colors.ATTRIBUTE_METER_WORSE)
  self._enablePreview = false
  self._baseValue = 0
  self._previewValue = 0
  self._hookTokens = {}
  self._textHandles = {}
  self._SetPreviewColor = args.SetPreviewColor
  self:SetGameObject(args.MeterObject)
  self:SetupText()
  if args.PreviewPercent ~= nil then
    self:AnimatePreviewBar(args.PreviewPercent)
  else
    self:AnimatePreviewBar(0)
  end
end
function MeterPreview:Activate()
  assert(not self._active)
  self._active = true
end
function MeterPreview:Deactivate()
  assert(self._active)
  self._active = false
  tablex.Clear(self._hookTokens)
end
function MeterPreview:Show()
  self._goMeter:Show()
  if self._goMeterChild ~= nil then
    self._goMeterChild:Show()
  end
  if self._goFill ~= nil then
    self._goFill:Show()
    if self._goFillChild ~= nil then
      self._goFillChild:Show()
    end
  end
  if self._goPreviewFill ~= nil then
    self._goPreviewFill:Show()
    if self._goPreviewFillChild ~= nil then
      self._goPreviewFillChild:Show()
    end
  end
end
function MeterPreview:Hide()
  self._goMeter:Hide()
end
function MeterPreview:SetPreviewColor(color)
  self._previewColor = color
  if self._SetPreviewColor ~= nil then
    self._SetPreviewColor(self, color)
  end
end
function MeterPreview:SetPreviewValue(value, rate)
  self._previewValue = value
  self:UpdateAll(rate)
end
function MeterPreview:SetBaseValue(value, rate)
  self._baseValue = value
  self:UpdateAll(rate)
end
function MeterPreview:DisablePreview()
  self._enablePreview = false
  self:UpdateAll(1)
end
function MeterPreview:EnablePreview()
  self._enablePreview = true
  self:UpdateAll(1)
end
function MeterPreview:UpdateAll(rate)
  local range = self._maxValue - self._minValue
  local baseValue = self._baseValue
  local basePercent = (baseValue - self._minValue) / range
  local previewValue = self._enablePreview and self._previewValue or baseValue
  local previewPercent = (previewValue - self._minValue) / range
  local valueDiff = math.floor(previewValue - baseValue)
  local finalBasePercent, finalPreviewPercent
  if valueDiff < 0 then
    finalBasePercent = previewPercent
    finalPreviewPercent = basePercent
  elseif 0 <= valueDiff then
    finalBasePercent = basePercent
    finalPreviewPercent = previewPercent
  end
  self:AnimateBaseBar(finalBasePercent, rate)
  self:AnimatePreviewBar(finalPreviewPercent, rate)
  self:SetText_BaseValue(baseValue)
  if valueDiff < 0 then
    self:SetText_PreviewValue(valueDiff)
    self:SetPreviewColor(self._worseColor)
  elseif 0 < valueDiff then
    self:SetText_PreviewValue(valueDiff)
    self:SetPreviewColor(self._betterColor)
  elseif valueDiff == 0 then
    self:SetText_PreviewValue(nil)
    self:SetPreviewColor({
      1,
      1,
      1
    })
  end
end
function MeterPreview:SetText_BaseValue(value)
  if value == nil then
    SetText(self._textHandles.thBaseText, "")
  else
    SetText(self._textHandles.thBaseText, string.format(self._textFormat, value))
  end
end
function MeterPreview:SetText_PreviewValue(value)
  if value == nil then
    SetText(self._textHandles.thPreviewText, "")
  else
    local colorStyleTag = "Color_Better"
    local printText = ""
    if 0 < value then
      printText = "+"
    else
      colorStyleTag = "Color_Worse"
    end
    printText = "<" .. colorStyleTag .. ">" .. printText .. string.format(self._textFormat, value) .. "</" .. colorStyleTag .. ">"
    SetText(self._textHandles.thPreviewText, printText)
  end
end
function MeterPreview:AnimateBaseBar(percent, rate)
  if percent < 0 then
    percent = 0
  elseif 1 < percent then
    percent = 1
  end
  self:SetPercent(percent, rate)
end
function MeterPreview:AnimatePreviewBar(percent, rate)
  if percent < 0 then
    percent = 0
  elseif 1 < percent then
    percent = 1
  end
  local itemToAnimate = self:GetInstancedPreviewFillObject()
  if itemToAnimate ~= nil then
    if rate == nil then
      UI.Anim(itemToAnimate, consts.AS_Forward, "", 0, percent)
    elseif percent > self._previewPercent then
      UI.Anim(itemToAnimate, consts.AS_Forward_NoReset, "", rate, self._previewPercent, percent)
    elseif percent < self._previewPercent then
      UI.Anim(itemToAnimate, consts.AS_Reverse_NoReset, "", rate, self._previewPercent, percent)
    end
  end
  self._previewPercent = percent
end
function MeterPreview:get_previewPercent()
  return self._previewPercent
end
function MeterPreview:SetupText()
  local goPreviewMeter = self._goMeter:FindSingleGOByName("previewMeter")
  local goTextGroup = goPreviewMeter:FindSingleGOByName("meter")
  self._textHandles.thPreviewText = GetTextHandle(goTextGroup, "text")
  local goBaseMeter = self._goMeter:FindSingleGOByName("baseMeter")
  goTextGroup = goBaseMeter:FindSingleGOByName("meter")
  self._textHandles.thBaseText = GetTextHandle(goTextGroup, "text")
end
function MeterPreview:ResetText()
  if self._textHandles ~= nil then
    SetText(self._textHandles.thBaseText, "")
    SetText(self._textHandles.thPreviewText, "")
  end
end
function MeterPreview:SetGameObject(goMeter)
  assert(goMeter ~= nil, "MeterPreview:SetGameObject called with no game object!")
  self._goMeter = goMeter
  if not util.IsStringNilOrEmpty(self._meterInstanceChildName) then
    self._goMeterChild = self._goMeter:FindSingleGOByName(self._meterInstanceChildName)
  end
  if not util.IsStringNilOrEmpty(self._fillObjectName) then
    self._goFill = self._goMeter:FindSingleGOByName(self._fillObjectName)
    if not util.IsStringNilOrEmpty(self._fillInstanceChildName) then
      self._goFillChild = self._goFill:FindSingleGOByName(self._fillInstanceChildName)
    end
  end
  if not util.IsStringNilOrEmpty(self._previewFillObjectName) then
    self._goPreviewFill = self._goMeter:FindSingleGOByName(self._previewFillObjectName)
    if not util.IsStringNilOrEmpty(self._previewFillInstanceChildName) then
      self._goPreviewFillChild = self._goPreviewFill:FindSingleGOByName(self._previewFillInstanceChildName)
    end
  end
end
function MeterPreview:GetInstancedPreviewFillObject()
  local obj
  if self._goMeterChild ~= nil then
    obj = self._goMeterChild
    if self._goPreviewFill ~= nil then
      obj = self._goPreviewFill
      if self._goPreviewFillChild ~= nil then
        obj = self._goPreviewFillChild
      end
    end
  end
  return obj
end
return {MeterPreview = MeterPreview}
