local item = class("cellTaskItem", G_UIModuleBase)
local _taskTpl = L_GameTpl:getTaskTpl()

function item.bind()
  return {
    taskDetails = "",
    taskTypeIcon = "",
    taskTypeIconColor = nil,
    taskDetailList = {
      moduleName = "pages/task/cellTaskDetail"
    },
    taskBtnObj = false,
    txtTraceName = L_WordsTpl:getValue("ui_task_newtask_tarck", {
      [0] = "V"
    })
  }
end

function item.methods()
  return {
    on_ClickOpenTask = function(self)
      local taskId = self.bind.taskId
      L_UI:open("pageTask", {taskId = taskId})
    end,
    on_ClickTraceButton = function(self)
      self:setTraceTask()
    end
  }
end

function item:close()
  self:reset()
end

function item:refreshTaskNpc()
  if not self.isOpen or math.isEmpty(self.bind.taskId) then
    return
  end
  self:refreshUI(self.bind.taskId)
end

function item:onShortCutEventTaskToMap()
  if self.bind.isNewTask then
    self:setTraceTask()
  end
end

function item:refreshTask()
  if not self.isOpen then
    return
  end
  self.taskId = self.bind.taskId
  self:refreshUI(self.bind.taskId)
  self:refreshTimers()
end

function item:refreshUI(taskId)
  self.bind.taskBtnObj = self.bind.isNewTask and not L_TaskManager:IsTaskInLimitStep(taskId)
  local tpl = _taskTpl:getTplById(taskId)
  local tabType = _taskTpl:getTabType(tpl)
  local taskTypeTpl = L_GameTpl:getTaskTypeTpl()
  local tplType = taskTypeTpl:getTplById(tabType)
  self.bind.taskDetails = _taskTpl:getName(tpl)
  self.bind.taskTypeIcon = taskTypeTpl:getIcon(tplType)
  if self.bind.isNewTask then
    self:refreshNewTaskDetailList(taskId)
  else
    self:refreshDetailList(taskId)
  end
end

function item:onTaskLimitUpdate(taskId)
  if self.bind.taskId == taskId then
    self:refreshDetailList(self.bind.taskId)
  end
end

function item:refresh()
  if self.bind.taskId < 0 then
    self:playHideAnim()
    return
  else
    self:refreshTask()
    if self.bind.isNewTask then
      self:playShowAnim(true)
      self:playDetailAnim(self.taskId ~= nil)
    elseif self.isPlayingHideAnim then
      self:playShowAnim(false)
    else
      self.parent:refreshTaskCutKey()
    end
  end
end

function item:refreshTimers()
  self:reset()
  if self.bind.taskBtnObj then
    L_ShortCutManager:addListener(L_ShortCutConst.event.TaskToMap, self.onShortCutEventTaskToMap, self)
  end
  if self.bind.taskDetails ~= "" then
    self.bind.startPosition = Unity.Vector3(0, 0, 0)
    local targetTransform = self.bindComponents.taskDetails.transform
    targetTransform.localPosition = self.bind.startPosition
    local text = targetTransform:GetComponent(typeof(C_LTextMeshProUGUI))
    local originText = text.text
    local count = string.getTextCount(originText)
    if 8 < count then
      text.text = string.subCountText(originText, 1, 8) .. "..."
      self.timer = Timer.repeated(10, function()
        text.text = originText
        self.tween = targetTransform:DOLocalMoveX(-200, 5):SetEase(Tweening.Ease.Linear):OnComplete(function()
          targetTransform.localPosition = self.bind.startPosition
          text.text = string.subCountText(originText, 1, 8) .. "..."
          if self.timer == nil then
            return
          end
          self.timer:pause()
          self.onceTimer = Timer.once(5, function()
            self.timer:resume()
          end, self)
        end, self)
      end, self, self.gameObject)
    end
  end
end

function item:setDetailanTrace(data, canTrace, traceText)
  data.traceText = traceText
  data.taskTrace = canTrace and traceText or ""
  data.traceLimit = not canTrace and traceText or ""
  data.activeTraceLimit = not canTrace and not string.isEmpty(traceText)
  data.taskBtnObj = canTrace
end

function item:refreshNewTaskDetailList(taskId)
  self.data = {}
  self.traceList = {}
  local infos = C_TaskManager.GetExecuteNodeInfoParam(taskId)
  if infos and infos.Count > 0 then
    for i = 0, infos.Count - 1 do
      local info = infos[i]
      if not info.isComplate then
        local data = C_TaskManager.GetTaskNodeCommonData(taskId, info.nodeId, info.index)
        local ele = {
          infoIndex = i,
          taskDetails = L_TaskManager:getTaskNodeTagetText(info, true),
          taskId = taskId,
          nodeId = info.nodeId,
          index = info.index,
          triggerType = data.triggerType,
          isSecondary = info.isUnneed
        }
        table.insert(self.data, ele)
      end
    end
  end
  self.bind.taskDetailList:clear()
  if #self.data > 0 then
    self.bind.taskDetailList:insert_array(self.data)
  end
end

function item:refreshDetailList(taskId)
  self.data = {}
  self.traceList = {}
  local infos = C_TaskManager.GetTaskTraceInfos(taskId)
  for i = 0, infos.Count - 1 do
    local taskInfo = infos[i]:GetTaskInfoData()
    local traceText = infos[i]:GetTraceSceneText()
    local ele = {
      taskDetails = L_TaskManager:getTaskNodeTagetText(taskInfo, true),
      taskId = taskId,
      nodeId = infos[i].NodeId,
      index = infos[i].Index,
      taskTrace = traceText,
      traceLimit = infos[i].limitText and infos[i].limitText.value or "",
      activeTraceLimit = infos[i].limitText and not string.isEmpty(infos[i].limitText.value),
      taskBtnObj = not string.isEmpty(traceText),
      isSecondary = taskInfo.isUnneed
    }
    if ele.taskBtnObj then
      local res = i + 1
      table.insert(self.traceList, res)
    end
    table.insert(self.data, ele)
  end
  local len = #self.data
  if 0 < len then
    local flag = 1 < len
    for i = 1, len do
      if not self.data[i].taskBtnObj or self.data[1].taskTrace ~= self.data[i].taskTrace then
        flag = false
        break
      end
    end
    if flag then
      local taskTrace = self.data[1].taskTrace
      local nodeId = self.data[1].nodeId
      local index = self.data[1].index
      for i = 1, len do
        self.data[i].taskBtnObj = false
        self.data[i].taskTrace = nil
      end
      local addData = {
        taskId = taskId,
        taskBtnObj = true,
        activeDetails = false,
        taskTrace = taskTrace,
        clickCB = function()
          self:openBigMap(taskId, nodeId, index)
        end
      }
      table.insert(self.data, addData)
      self.bind.taskDetailList:insert_array(self.data)
      self.traceList = {
        #self.data
      }
    else
      for i = 1, len do
        if self.data[i].taskBtnObj then
          local nodeId = self.data[i].nodeId
          local index = self.data[i].index
          self.data[i].clickCB = function()
            self:openBigMap(taskId, nodeId, index)
          end
        end
      end
    end
  end
  self.bind.taskDetailList:clear()
  if #self.data > 0 then
    self.bind.taskDetailList:insert_array(self.data)
  elseif C_BattleManager:IsInBattle() then
    self.data = {
      {
        taskId = taskId,
        taskDetails = L_WordsTpl:getValue("ui_fight_task_notice")
      }
    }
    self.bind.taskDetailList:insert_array(self.data)
  end
  Unity.UI.LayoutRebuilder.ForceRebuildLayoutImmediate(self.bindComponents.transTargets)
  local minY = -self.bindComponents.transTargets.offsetMin.y
  local size = self.bindComponents.layoutElem.transform.sizeDelta
  size.y = minY
  self.bindComponents.layoutElem.transform.sizeDelta = size
  self.bindComponents.layoutElem.preferredHeight = minY
end

function item:playDetailAnim(isNew, cb)
  local detailAnim = isNew and "anim_taskitem_detail_new_in" or "anim_taskitem_detail_in"
  for i = 1, #self.modules.taskDetailList do
    self.modules.taskDetailList[i]:playAnim(detailAnim)
  end
  if cb then
    if isNew then
      L_TimerManager:newOrResetTimer(self, "refreshAnim", function()
        cb()
      end, 1)
    else
      cb()
    end
  end
end

function item:reset()
  if self.timer then
    self.timer:destroy()
    Timer.remove(self.timer)
    self.timer = nil
  end
  if self.onceTimer then
    self.onceTimer:destroy()
    Timer.remove(self.onceTimer)
    self.onceTimer = nil
  end
  if self.tween then
    self.tween:Kill()
  end
  L_TimerManager:clearTimer(self)
  L_ShortCutManager:removeListener(L_ShortCutConst.event.TaskToMap, self.onShortCutEventTaskToMap, self)
end

function item:showCutKey()
  if self.traceList[1] then
    local subClass = self.bind.taskDetailList:getItemCls(self.traceList[1])
    if subClass then
      subClass:showCutKey()
    end
  end
end

function item:hideCutKey()
  for i = 1, #self.modules.taskDetailList do
    self.modules.taskDetailList[i]:hideCutKey()
  end
end

function item:openBigMap(taskId, nodeId, index)
  C_TaskManager.OpenMapByTaskId(taskId, nodeId, index)
end

function item:setTraceTask()
  L_TaskStore:setTraceTask(self.bind.taskId, function()
    self.bind.taskBtnObj = false
    self.parent:taskUpdateAndNewAnim()
  end)
end

function item:playAnim(name)
  self.bindComponents.animation:Stop()
  self.bindComponents.animation:Play(name)
end

function item:playShowAnim(isNew)
  self.isPlayingHideAnim = false
  self:playAnim(isNew and "anim_taskitem_new_in" or "anim_taskitem_in")
end

function item:playHideAnim(cb)
  self.isPlayingHideAnim = true
  for i = 1, #self.modules.taskDetailList do
    self.modules.taskDetailList[i]:hideCutKey()
  end
  self:playAnim("anim_taskitem_out")
  if self.bind.taskBtnObj then
    self.bindComponents.animTraceBtn:Stop()
    self.bindComponents.animTraceBtn:Play("anim_taskitem_button_out")
  end
  if cb then
    L_TimerManager:newOrResetTimer(self, "refreshAnim", function()
      cb()
    end, 0.2)
  end
end

function item:tryPlayUpdateAnim(cb)
  if not self.data then
    return
  end
  local nodeId = C_TaskManager.GetExcuteNode(self.bind.taskId)
  if not nodeId then
    self:hideCutKey()
    L_TimerManager:newOrResetTimer(self, "refreshAnim", function()
      self:playHideAnim(cb)
    end, 0.833)
  else
    local complateDetails
    if self.bind.nodeId ~= nodeId then
      complateDetails = self.modules.taskDetailList
    else
      complateDetails = {}
      local infos = L_TaskManager:GetNodeInfoParam(self.bind.taskId, nodeId)
      for i = 1, #self.modules.taskDetailList do
        if self.modules.taskDetailList[i].activeDetails then
          local detail = self.modules.taskDetailList[i]
          if infos.Count > detail.bind.index then
            local info = infos[detail.bind.index]
            if info.isComplate then
              table.insert(complateDetails, detail)
            end
          end
        end
      end
    end
    if 0 < #complateDetails then
      for i = 1, #complateDetails do
        complateDetails[i]:hideCutKey()
        complateDetails[i]:playAnim("anim_taskitem_detail_complete")
        L_AudioUtil.playSound("Play_SFX_System_HUD_Mission_PartFinish")
      end
      L_TimerManager:newOrResetTimer(self, "refreshAnim", function()
        for i = 1, #complateDetails do
          if not complateDetails[i].isBind then
            break
          end
          complateDetails[i]:playAnim("anim_taskitem_detail_out")
        end
        L_TimerManager:newOrResetTimer(self, "refreshAnim", function()
          if self.bind.nodeId ~= nodeId then
            self.bind.nodeId = nodeId
          end
          self:refreshDetailList(self.bind.taskId)
          self:playDetailAnim(true, cb)
        end, 0.25)
      end, 0.833)
    elseif cb then
      cb()
    end
  end
end

return item
