local this = class("pageActivityTask", G_UIPageBase)
local noviceTaskTpl = L_GameTpl:getNoviceTaskTpl()
local noviceTaskGroupTpl = L_GameTpl:getNoviceTaskGroupTpl()
local activityTabTpl = L_GameTpl:getActivityTabTpl()
local _unitTpl = L_GameTpl:getUnitTpl()
local PETSCENEPATH = "Program/UIScene/pre_activtityScene_ui_01.prefab"
local PageContentType = {DAILY_TASK = 1, NOVICE_TASK = 2}
local SwitchNoviceTaskGroupDirection = {TURN_LEFT = 1, TURN_RIGHT = 2}
local ActivityType = {DAILY_TASK = 1, NOVICE_TASK = 2}
local ActivityType2TableId = {
  [ActivityType.DAILY_TASK] = 1,
  [ActivityType.NOVICE_TASK] = 2
}

function this:initCharactorSceneAsync()
  self.sceneGo = L_ResPool:syncGameObject(PETSCENEPATH)
  local sceneTrans = self.sceneGo.transform
  self.sceneCameraTrans = sceneTrans:Find("camera")
  self.bgDay = sceneTrans:Find("bg_day").gameObject
  self.bgWeek = sceneTrans:Find("bg_week").gameObject
  self.bgDay:ActiveTrans(true)
  self.bgWeek:ActiveTrans(false)
  sceneTrans:SetParent(C_LuaUtility.GetRootNode())
  local controlEntity = L_PlayerManager:getMainControlEntity()
  if controlEntity then
    local pos = controlEntity:getPosition()
    L_Vector3.setPos(sceneTrans, L_Vector3.new(pos.x, pos.y - 50, pos.z))
  else
    L_Vector3.setPos(sceneTrans, L_Vector3.zero)
  end
  L_Vector3.setLocalPos(self.sceneCameraTrans, L_Vector3.new(0.75, 4.5, 28))
  L_Vector3.setLocalRot(self.sceneCameraTrans, L_Vector3.new(7, 180, 0))
  L_Vector3.setRot(sceneTrans, L_Vector3.zero)
  local charactorUnitId = 101001
  local charactorModelPath = _unitTpl:getModel(_unitTpl:getTplById(charactorUnitId), L_Const.avatarModelIndex.UnitModel)
  local go = L_ResPool:syncGameObject(charactorModelPath)
  local charactorGo = go
  self.charactorGo = charactorGo
  charactorGo.name = "charactor"
  if L_CommonUtil.isValid(self.sceneGo) then
    local transPointCharactor = self.sceneGo.transform:Find("point_charactor")
    charactorGo.transform:SetParent(transPointCharactor)
    L_Vector3.setLocalPos(charactorGo.transform, L_Vector3.new(1.18, 3.51, 26.49))
    L_Vector3.setLocalPos(charactorGo.transform:GetChild(0).gameObject.transform, L_Vector3.new(0.05, 0, -0.26))
    local quaternion = Unity.Quaternion.Euler(0, -2.25, 0)
    charactorGo.transform.localRotation = quaternion
    local charactorEntity = require(L_EcsConst.aliveType.previewNpc).new(L_EcsConst.aliveType.previewNpc)
    charactorEntity:initPreview(charactorUnitId, charactorGo)
    self.charactorEntity = charactorEntity
    self.charactorEntity.gameObject:ActiveTrans(false)
    L_SceneManager:setSceneActive(false)
    self.sceneCameraTrans.gameObject:SetActive(true)
    self.canShowUiAndCamera = true
    self.canInitUiAndCamera = true
  end
end

function this.bind()
  return {
    activityRewardList = {
      moduleName = "pages/activityTask/cellActivityRewardItem"
    },
    activityTaskList = {},
    active_dailyBg = true,
    active_weekBg = false,
    activityCount = "",
    totalActivity = "",
    timeTxt = "",
    activityType = "",
    activityRewardList_week = {
      moduleName = "pages/activityTask/cellActivityRewardItem"
    },
    activityTaskList_week = {},
    activityCount_week = "",
    totalActivity_week = "",
    timeTxt_week = "",
    activityType_week = "",
    go_contentToggle = true,
    go_contentDailyTask = true,
    go_contentNoviceTask = false,
    toggle_isOn = true
  }
end

function this.methods()
  return {
    onClick_close = function(self)
      L_UI:close(self.pageName)
    end,
    onValueChanged_dairy = function(self)
      self:switchTaskPage(1)
    end,
    onValueChanged_week = function(self)
      self:switchTaskPage(2)
    end,
    activityRewardList = {
      onClick_getReward = function(self, data)
        self:onClickRewardList()
      end,
      onClick_rewardPreview = function(self, bool)
        self:onClickPreviewReward(bool)
      end,
      onOpen_rewardPreview = function(self, rect)
        self:onOpenPreviewReward(rect)
      end
    },
    activityTaskList = {
      onClick_receive = function(self, data)
        self:onClickActivityList(data)
      end
    },
    activityRewardList_week = {
      onClick_getReward = function(self, data)
        self:onClickRewardList()
      end,
      onClick_rewardPreview = function(self, bool)
        self:onClickPreviewReward(bool)
      end,
      onOpen_rewardPreview = function(self, rect)
        self:onOpenPreviewReward(rect)
      end
    },
    activityTaskList_week = {
      onClick_receive = function(self, data)
        self:onClickActivityList(data)
      end
    },
    onClick_bg = function(self)
    end
  }
end

function this:ctor(...)
  this.super.ctor(self, ...)
  self.data = {
    activityDotQueue = L_Struct.getQueue()
  }
end

function this:check(options, callback)
  if L_DungeonManager:getIsInTrainTaskDungeon() then
    callback(false)
    return
  end
  local result = self:checkIfCanOpen()
  callback(result)
end

function this:checkIfCanOpen()
  if not L_SystemUnlockStore:getSystemIsOpen(L_SystemConst.enum.activation) then
    return false
  end
  return true
end

function this:preOpen(options)
  this.super.preOpen(self, options)
  C_CameraManager.SetBrainBlendStyle(L_Const.blendStyle.cut)
  local brain = C_CameraManager.GetMainCameraBrain()
  brain.m_CustomBlends = nil
  self:initCharactorSceneAsync()
  L_ActivityTaskStore:listenCallFunc(L_ActivityTaskStore.event.refreshActivityTask, self.onEvent_refresh, self)
  L_ActivityTaskStore:listenCallFunc(L_ActivityTaskStore.event.refreshActivityReward, self.onEvent_refreshReward, self)
  self.activtyTaskData = nil
  self.activityRewardData = nil
  self.bind.activityType = L_WordsTpl:getValue("ui_pageActivityTask_03")
  self.bind.activityType_week = L_WordsTpl:getValue("ui_pageActivityTask_02")
  if options and options.jumpParams then
    self.titleType = tonumber(options.jumpParams[1])
  else
    self.titleType = 1
  end
  self:initToggle(self.titleType)
  self:initTaskPage(self.titleType)
  self.isDuringOpenAnim = true
  self.bindComponents.mainPanelAni:Stop()
  if options and options.noOpenAnim then
    self.bindComponents.mainPanelAni:Play("anim_AT_content_init")
  else
    self.bindComponents.mainPanelAni:Play("anim_AT_content_showD")
  end
end

function this:open(options)
  if self.charactorEntity then
    self.charactorEntity.gameObject:ActiveTrans(true)
    self.timer = Timer.once(0, function()
      self.charactorEntity.playableAnimator:Play("Activity_DayEntry")
      self.timer = nil
    end, self, self.gameObject)
  end
end

function this:show()
  self:initReddot()
  self:initTitleType()
  if L_CommonUtil.isValid(self.sceneGo) then
    L_Vector3.setLocalPos(self.sceneCameraTrans, L_Vector3.new(0.75, 4.5, 28))
    L_Vector3.setLocalRot(self.sceneCameraTrans, L_Vector3.new(7, 180, 0))
    self.sceneCameraTrans.gameObject:SetActive(true)
  end
  if self.isDuringOpenAnim then
    self.isDuringOpenAnim = nil
  end
end

function this:refreshPageView(options)
  options = options or {}
  if options.jumpParams then
    if self.titleType ~= tonumber(options.jumpParams[1]) then
      self.bind.toggle_isOn = tonumber(options.jumpParams[1]) == 1
    end
    self:switchTaskPage(tonumber(options.jumpParams[1]))
  end
end

function this:hide()
  if L_CommonUtil.isValid(self.sceneGo) then
    self.sceneCameraTrans.gameObject:SetActive(false)
  end
  self.bindComponents.FX.gameObject:SetActive(false)
end

function this:close()
  self:disposeTimer()
  self.titleType = nil
  self.activtyTaskData = nil
  self.activityRewardData = nil
  if L_CommonUtil.isValid(self.sceneGo) then
    C_GameObject.Destroy(self.sceneGo)
  end
  L_ActivityTaskStore:unListenCallFunc(L_ActivityTaskStore.event.refreshActivityTask, self.onEvent_refresh)
  L_ActivityTaskStore:unListenCallFunc(L_ActivityTaskStore.event.refreshActivityReward, self.onEvent_refreshReward)
end

function this:initTitleType()
  if math.isEmpty(self.titleType) then
    self.titleType = 1
  end
  self:refreshActivityData(self.titleType)
end

function this:onHideTitleType()
  self.titleType = nil
end

function this:onEvent_refreshReward()
  if math.isEmpty(self.titleType) then
    self.titleType = 1
  end
  self:refreshActivityRewardState(self.titleType)
  local targetActivity = self.titleType == 1 and L_ActivityTaskStore:getTodayActivityValue() or L_ActivityTaskStore:getWeekActivityValue()
  if self.beginActivity ~= targetActivity and self.beginActivity < self.maxActivity then
    if targetActivity >= self.maxActivity then
      targetActivity = self.maxActivity
    end
    if self.titleType == 1 then
      self.bind.activityCount = tostring(self.beginActivity)
    else
      self.bind.activityCount_week = tostring(self.beginActivity)
    end
    local getter = function()
      return self.beginActivity
    end
    local setter = function(v)
      if self.titleType == 1 then
        self.bind.activityCount = tostring(math.floor(v))
      else
        self.bind.activityCount_week = tostring(math.floor(v))
      end
    end
    if self.activityTween then
      self.activityTween:Kill()
      self.beginActivity = self.nextActivity or self.beginActivity
    end
    self.nextActivity = targetActivity
    self.activityTween = DOTween.To(getter, setter, targetActivity, 0.6):SetEase(Tweening.Ease.Linear):OnComplete(function()
      self.beginActivity = targetActivity
      self.nextActivity = nil
    end)
    self.activityTween:SetAutoKill(true)
    self.activityTween:Play()
  end
end

function this:onEvent_refresh()
  if math.isEmpty(self.titleType) then
    self.titleType = 1
  end
  self:refreshActivityData(self.titleType)
  self.bindComponents.menuCanvas.interactable = false
  self:refreshList()
end

function this:initReddot()
  local reddotMap = {
    [L_ReddotManager.DotDef.DairyActivity] = self.bindComponents.toggleDailyTaskReddot,
    [L_ReddotManager.DotDef.WeeklyActivity] = self.bindComponents.toggleWeeklyTaskReddot
  }
  for key, go in pairs(reddotMap) do
    L_ReddotManager:registerReddot(go, key)
  end
end

function this:initTaskPage(titleType)
  self:refreshTaskPage(titleType)
  self.beginActivity = titleType == 1 and L_ActivityTaskStore:getTodayActivityValue() or L_ActivityTaskStore:getWeekActivityValue()
end

function this:switchTaskPage(titleType)
  if self.titleType == titleType then
    return
  end
  self:disposeTimer()
  self:refreshTaskPage(titleType)
  if self.titleType == 1 and titleType == 2 then
    C_AudioManager.Play("Play_SFX_System_UI_Activity_Type_Select")
  elseif self.titleType == 2 and titleType == 1 then
    C_AudioManager.Play("Play_SFX_System_UI_Activity_Type_Select")
  end
  self.titleType = titleType
  self.bind.active_dailyBg = titleType == 1 and true or false
  self.bind.active_weekBg = titleType == 2 and true or false
  self.bgDay:ActiveTrans(titleType == 1)
  self.bgWeek:ActiveTrans(titleType == 2)
  self.beginActivity = titleType == 1 and L_ActivityTaskStore:getTodayActivityValue() or L_ActivityTaskStore:getWeekActivityValue()
end

function this:refreshTaskPage(index)
  self:refreshActivityData(index)
  self:startDateTimer(index)
  self:refreshActivityTaskList(index)
  self:refreshActivityRewardList(index)
end

function this:onClickGetAll()
  if self:isExsistCanRewardData() == true then
    local ids = {}
    local taskList = self.titleType == 1 and self.bind.activityTaskList or self.bind.activityTaskList_week
    for i = 1, #taskList do
      local curActivityId = taskList:getValue(i, "curActivityId")
      if not math.isEmpty(curActivityId) then
        local isFinish = taskList:getValue(i, "finishState") == 1
        local canClick = taskList:getValue(i, "show_receiveBtn")
        if isFinish and canClick then
          taskList:getItemCls(i):onClick()
          local id = curActivityId
          table.insert(ids, id)
        end
      end
    end
    L_ActivityTaskStore:req_getActivityItemReward(ids, function()
      self:refreshList()
      self:playAnim()
    end)
  else
    L_FlyMsgManager:showNormalMsg(L_WordsTpl:getValue("ui_challenge_11"))
  end
end

function this:setTipActive()
  if self.bind.go_rewardTip then
    self.bind.go_rewardTip = false
  else
    self.bind.go_rewardTip = true
  end
end

function this:isExsistCanRewardData()
  local canReward = false
  for i, v in pairs(self.activtyTaskData) do
    if v.finishState == 1 then
      canReward = true
      break
    end
  end
  return canReward
end

function this:refreshOneClickButton(index)
  local moduleButton = self.modules.moduleButton
  local allReceived = true
  for i, v in ipairs(self.activtyTaskData) do
    if v.finishState ~= 2 then
      allReceived = false
    end
  end
  if index == 1 then
    self.bind.show_allReceived = false
    self.bind.show_receiveButton = false
  else
    self.bind.show_allReceived_week = false
    self.bind.show_receiveButton_week = false
  end
  if self:isExsistCanRewardData() == true then
    moduleButton:setData(L_Const.ButtonType.BLUE, L_WordsTpl:getValue("ui_cellNoviceTaskItem_05"), handler(self, self.onClickGetAll))
  else
    moduleButton:setData(L_Const.ButtonType.GREY, L_WordsTpl:getValue("ui_cellNoviceTaskItem_05"), handler(self, self.onClickGetAll))
  end
end

function this:refreshActivityData(index)
  self.activtyTaskData = L_ActivityTaskStore:getActivityTaskGroupByIndex(index)
  self.activityRewardData = L_ActivityTaskStore:getActivityRewardListByIndex(index)
  local curActivity = index == 1 and L_ActivityTaskStore:getTodayActivityValue() or L_ActivityTaskStore:getWeekActivityValue()
  self.maxActivity = self.activityRewardData[#self.activityRewardData].requireActivity
  if curActivity >= self.maxActivity then
    if index == 1 then
      self.bind.activityCount = tostring(self.maxActivity)
    else
      self.bind.activityCount_week = tostring(self.maxActivity)
    end
  elseif index == 1 then
    self.bind.activityCount = tostring(curActivity)
  else
    self.bind.activityCount_week = tostring(curActivity)
  end
end

function this:refreshActivityTaskList(index)
  local activityTaskList = index == 1 and self.bind.activityTaskList or self.bind.activityTaskList_week
  activityTaskList:clear()
  local taskData = {}
  local canReceived = false
  local receiveCount = 0
  for i, v in ipairs(self.activtyTaskData) do
    if math.isEmpty(v.unlockSystemId) or L_SystemUnlockStore:getSystemIsOpen(v.unlockSystemId) then
      if v.finishState == 1 then
        receiveCount = receiveCount + 1
        canReceived = 1 < receiveCount
      end
      table.insert(taskData, {
        describe = v.describe,
        taskActivityReward = v.reward,
        itemReward = v.itemReward,
        count = v.count >= v.targetCount and v.targetCount or v.count,
        targetCount = v.targetCount,
        groupId = v.groupId,
        curActivityId = v.id,
        finishState = v.finishState,
        systemId = v.systemId,
        index = index,
        identify = "cellTaskItem",
        moduleName = "pages/ActivityTask/cellActivityTaskItem"
      })
    end
  end
  if canReceived then
    table.insert(taskData, 1, {
      curActivityId = 0,
      systemId = 0,
      identify = "cellActivityTaskReceiveAll",
      moduleName = "pages/activityTask/cellActivityTaskReceiveAll"
    })
  end
  activityTaskList:insert_array(taskData)
end

function this:refreshActivityRewardList(index)
  local activityRewardList = index == 1 and self.bind.activityRewardList or self.bind.activityRewardList_week
  self.activityRewardData = L_ActivityTaskStore:getActivityRewardListByIndex(index)
  activityRewardList:clear()
  local rewardData = {}
  for i, v in ipairs(self.activityRewardData) do
    table.insert(rewardData, {
      activityReward = tostring(v.requireActivity),
      canReward = v.canReward == 1 and v.isFinish == false and true or false,
      activityRewardId = v.id,
      isActive = v.canReward == 1 and true or false,
      reward = v.reward,
      isFinish = v.isFinish == true and true or false,
      curTotalActivity = v.curTotalActivity,
      requireActivity = v.requireActivity,
      lastActivity = self.activityRewardData[i - 1] and self.activityRewardData[i - 1].requireActivity or 0,
      isEndIndex = #self.activityRewardData == i
    })
    if #self.activityRewardData == i then
      if index == 1 then
        self.bind.totalActivity = string.format("/%d", v.requireActivity)
      else
        self.bind.totalActivity_week = string.format("/%d", v.requireActivity)
      end
    end
  end
  activityRewardList:insert_array(rewardData)
end

function this:refreshActivityRewardState(index)
  local activityRewardList = index == 1 and self.bind.activityRewardList or self.bind.activityRewardList_week
  self.activityRewardData = L_ActivityTaskStore:getActivityRewardListByIndex(self.titleType)
  for i = 1, #self.activityRewardData do
    local v = self.activityRewardData[i]
    activityRewardList:change(i, {
      curTotalActivity = v.curTotalActivity
    })
  end
  local refreshSingleReward = function(data, index)
    local v = data
    activityRewardList:change(index, {
      canReward = v.canReward == 1 and v.isFinish == false and true or false,
      isActive = v.canReward == 1 and true or false,
      isFinish = v.isFinish == true and true or false,
      curTotalActivity = v.curTotalActivity,
      requireActivity = v.requireActivity,
      lastActivity = self.activityRewardData[index - 1] and self.activityRewardData[index - 1].requireActivity or 0
    })
  end
  local hasRefreshed = false
  if self.dotLineTimer then
    Timer.remove(self.dotLineTimer)
    self.dotLineTimer = nil
    self:refreshActivityRewardQuickly(activityRewardList)
    hasRefreshed = true
  end
  self.data.activityDotQueue:clean()
  for i, v in ipairs(activityRewardList) do
    local canTween = activityRewardList:getItemCls(i):isVisibleTween()
    if canTween then
      self.data.activityDotQueue:enQueue({
        item = activityRewardList:getItemCls(i),
        new_data = self.activityRewardData[i],
        index = i
      })
    end
  end
  if self.data.activityDotQueue:getLength() > 0 then
    self:activityQueueDealFirst(refreshSingleReward)
    self.dotLineTimer = Timer.repeated(0.16, function()
      if self.data.activityDotQueue:getLength() > 0 then
        self:activityQueueDealFirst(refreshSingleReward)
      else
        self.data.activityDotQueue:clean()
        if self.dotLineTimer then
          Timer.remove(self.dotLineTimer)
          self.dotLineTimer = nil
          self:refreshActivityRewardQuickly(activityRewardList)
        end
      end
    end, self, self.gameObject)
  elseif not hasRefreshed then
    self:refreshActivityRewardQuickly(activityRewardList)
  end
end

function this:activityQueueDealFirst(func)
  local first = self.data.activityDotQueue:getFirst()
  func(first.new_data, first.index)
  first.item:dotLineTween()
  self.data.activityDotQueue:deQueue()
end

function this:refreshActivityRewardQuickly(activityRewardList)
  self.activityRewardData = L_ActivityTaskStore:getActivityRewardListByIndex(self.titleType)
  for i = 1, #self.activityRewardData do
    local v = self.activityRewardData[i]
    activityRewardList:change(i, {
      activityReward = tostring(v.requireActivity),
      canReward = v.canReward == 1 and v.isFinish == false and true or false,
      activityRewardId = v.id,
      isActive = v.canReward == 1 and true or false,
      reward = v.reward,
      isFinish = v.isFinish == true and true or false,
      curTotalActivity = v.curTotalActivity,
      requireActivity = v.requireActivity,
      lastActivity = self.activityRewardData[i - 1] and self.activityRewardData[i - 1].requireActivity or 0,
      isEndIndex = #self.activityRewardData == i
    })
  end
end

function this:playAnim()
  if self.charactorEntity == nil then
    return
  end
  local animName = self.titleType == 1 and "Activity_Praise" or "Activity_Prase_2"
  self.charactorEntity.playableAnimator:Play(animName)
end

function this:onClickRewardList()
  L_ActivityTaskStore:req_getActivityTaskReward(self.titleType, function()
    self:playAnim()
  end)
end

function this:onClickPreviewReward(bool)
  if bool then
    local activityRewardList = self.titleType == 1 and self.bind.activityRewardList or self.bind.activityRewardList_week
    for i = 1, #activityRewardList do
      activityRewardList:change(i, {show_rewardPreview = false})
    end
  end
end

function this:onClickActivityList(data)
  if math.isEmpty(data.curActivityId) then
    self:onClickGetAll()
  else
    local ids = {}
    table.insert(ids, data.curActivityId)
    L_ActivityTaskStore:req_getActivityItemReward(ids, function()
      self.bindComponents.boardAni:Stop()
      self.bindComponents.boardAni:Play("anim_AT_content_gain")
      self:playAnim()
    end)
  end
end

function this:refreshList()
  L_TimerManager:newOrResetTimer(self, "refreshActivityList", function()
    self.bindComponents.boardAni:Stop()
    self.bindComponents.boardAni:Play("anim_AT_content_hide")
    self:refreshActivityTaskList(self.titleType)
    self.bindComponents.boardAni:Play("anim_AT_content_fresh")
    self.bindComponents.menuCanvas.interactable = true
  end, 1)
end

function this:startDateTimer(index)
  self:disposeTimer()
  local freshFunc
  if index == 1 then
    function freshFunc()
      return L_TimeUtil.getLeftDayRefreshTime()
    end
    
    self.bind.timeTxt = freshFunc()
  elseif index == 2 then
    function freshFunc()
      return L_TimeUtil.getLeftWeekRefreshTime()
    end
    
    self.bind.timeTxt_week = freshFunc()
  end
  self.timer = Timer.repeated(1, function()
    if index == 1 then
      self.bind.timeTxt = freshFunc()
    elseif index == 2 then
      self.bind.timeTxt_week = freshFunc()
    end
  end, self, self.gameObject)
end

function this:disposeTimer()
  if self.timer ~= nil then
    Timer.remove(self.timer)
    self.timer = nil
  end
  if self.activityTween ~= nil then
    self.activityTween:Kill()
    self.activityTween = nil
  end
  L_TimerManager:clearTimer(self)
end

function this:initToggle(selectType)
  self.bind.go_contentToggle = true
  self:switchPageContent(selectType)
end

function this:switchPageContent(pageContentType)
  self.bind.go_contentDailyTask = pageContentType == PageContentType.DAILY_TASK
  self.bind.go_contentNoviceTask = pageContentType == PageContentType.NOVICE_TASK
end

function this:closeRewardTips()
  local activityRewardList = self.titleType == 1 and self.bind.activityRewardList or self.bind.activityRewardList_week
  for i = 1, #activityRewardList do
    activityRewardList:change(i, {show_rewardPreview = false})
  end
end

function this:onOpenPreviewReward(rect)
  self.rewardPreviewRect = rect
end

function this:update()
  if self.rewardPreviewRect ~= nil and self.rewardPreviewRect.gameObject.activeInHierarchy and Unity.Input.GetMouseButtonDown(0) then
    local rect = self.rewardPreviewRect
    local mousePositionV2 = C_Vector2(Unity.Input.mousePosition.x, Unity.Input.mousePosition.y)
    local isUI = Unity.RectTransformUtility.RectangleContainsScreenPoint(rect, mousePositionV2, C_CameraManager.uiCamera)
    if not isUI then
      self:closeRewardTips()
      return
    end
  end
end

return this
