local this = class("pageCollection", G_UIPageBase)
local _homeBuildingCollectionTpl = L_GameTpl:getHomeBuildingCollectionTpl()
local _productsTpl = L_GameTpl:getProductsCollectionTpl()
local _productsCollectionTypeTpl = L_GameTpl:getProductsCollectionTypeTpl()
local _homeCollectionWorkLimitTpl = L_GameTpl:getHomeCollectionWorkLimitTpl()

function this.bind()
  return {
    go_free = false,
    txt_time_free = nil,
    txt_time_title = true,
    go_working = false,
    go_running = false,
    txt_time_running = nil,
    go_finish = false,
    go_btn_collect = false,
    go_pause = true,
    txt_pause = nil,
    go_full = false,
    scrollList_preview = {
      moduleName = "pages/collection/cellCollectionPreview"
    },
    scrollList_output = {
      moduleName = "pages/collection/cellCollectionOutput"
    },
    module_stationInfo = {
      moduleName = "pages/home/homeStation/moduleStationInfo"
    },
    txt_workLimit = "",
    module_homeProperty = {
      moduleName = "pages/home/homeProperty/moduleHomeProperty"
    }
  }
end

function this.methods()
  return {
    onClick_close = function(self)
      self:closeCheck()
    end,
    onClick_start = function(self)
      self:checkCollect()
    end,
    onClick_collect = function(self)
      L_CollectionManager:reqCollectReward(self._collectionGuid, nil, function()
        self:initOutputList(true)
      end)
    end
  }
end

function this:preOpen(options)
  this.super.preOpen(self, options)
  L_HomeStore:listenCallFunc(L_HomeStore.event.syncWorldMapHomeItem, self.refreshProperty, self)
  L_HomeStore:listenCallFunc(L_HomeStore.event.syncWorldMapHomeItem, self.refreshCollectionBuildingWorkLimitPart, self)
  L_PetStore:listenCallFunc(L_PetStore.event.refreshBuildingPet, self.onEvent_refreshPet, self)
  L_CollectionStore:listenCallFunc(L_CollectionStore.event.updateCollection, self.onEvent_updateCollection, self)
  L_CollectionStore:listenCallFunc(L_CollectionStore.event.refreshCollection, self.onEvent_refreshCollection, self)
  self:registerConditionsOfUnlockMaxWorkingNumOfCollectionBuildingAtSameTime()
  self._collectionGuid = options.guid
  if options.entity then
    self:loadVirtualCamera(options.entity)
    self._hasEntity = true
  end
  self:initPage(true)
end

function this:close(options)
  this.super.close(self, options)
  if self._hasEntity then
    self:unloadVirtualCamera()
    self._hasEntity = nil
  end
  L_TimerManager:clearTimer(self)
  L_HomeStore:unListenCallFunc(L_HomeStore.event.syncWorldMapHomeItem, self.refreshProperty)
  L_HomeStore:unListenCallFunc(L_HomeStore.event.syncWorldMapHomeItem, self.refreshCollectionBuildingWorkLimitPart)
  L_PetStore:unListenCallFunc(L_PetStore.event.refreshBuildingPet, self.onEvent_refreshPet)
  L_CollectionStore:unListenCallFunc(L_CollectionStore.event.updateCollection, self.onEvent_updateCollection)
  L_CollectionStore:unListenCallFunc(L_CollectionStore.event.refreshCollection, self.onEvent_refreshCollection)
  self:unregisterConditionsOfUnlockMaxWorkingNumOfCollectionBuildingAtSameTime()
end

function this:show()
  for i, v in pairs(self.modules.scrollList_preview) do
    v:setMaskActive(true)
  end
end

function this:hide()
  for i, v in pairs(self.modules.scrollList_preview) do
    v:setMaskActive(false)
  end
end

function this:initPage(needSort)
  local serverData = L_CollectionStore:getCollection(self._collectionGuid)
  local isWorking = not math.isEmpty(serverData.start_time)
  self.bind.go_free = not isWorking
  self.bind.go_working = isWorking
  if isWorking then
    self:openTickTimer()
  else
    self:calculateCostTime(serverData)
  end
  self:refreshPauseInfo()
  self:initOutputList(needSort)
  local moduleStationInfo = self.modules.module_stationInfo
  moduleStationInfo:setCollectionModule(self._collectionGuid)
  self.modules.module_homeProperty:setRanchBlock(self._collectionGuid)
  if serverData.build_id ~= self._buildingId then
    self:initPreviewList()
    self._buildingId = serverData.build_id
  end
  self.modules.module_homeProperty:setCollection(self._collectionGuid)
  self:refreshCollectionBuildingWorkLimitPart()
end

function this:calculateCostTime(serverData)
  local nowTime = L_TimeUtil.getServerTime()
  local pet = L_PetStore:getPetItem(serverData.pet_guid)
  local endTime = L_SatietyStore:calculateSatietyTimeStamp(pet)
  local leftTime = endTime - nowTime
  if 0 < leftTime then
    self.bind.txt_time_free = L_TimeUtil.secondToLangString(leftTime)
  else
    self.bind.txt_time_free = ""
  end
end

function this:initPreviewList()
  local serverData = L_CollectionStore:getCollection(self._collectionGuid)
  local tpl_building = _homeBuildingCollectionTpl:getTplById(serverData.build_id)
  local level = _homeBuildingCollectionTpl:getLevel(tpl_building)
  local products, extras = _homeBuildingCollectionTpl:getMaxLevelProducts(self._collectionGuid)
  local productIds = {}
  for i, productId in ipairs(products) do
    table.insert(productIds, productId)
  end
  for i, productId in ipairs(extras) do
    table.insert(productIds, productId)
  end
  local tmp = {}
  for i, productId in ipairs(productIds) do
    local tpl_pro = _productsTpl:getTplById(productId)
    local dropUnlockLevel = _productsTpl:getDropUnlockLevel(tpl_pro)
    local dropType = _productsTpl:getDropType(tpl_pro)
    local reward = L_DataUtil.parseRewardConfigItem(_productsTpl:getDropShow(tpl_pro)[1])
    local configData = L_ItemTplManager:getItemConfig(reward.itemType, reward.itemId)
    local tpl_dropType = _productsCollectionTypeTpl:getTplById(dropType)
    local isLock = level < dropUnlockLevel
    local isShowRare = _productsCollectionTypeTpl:getIsShowInOutPut(tpl_dropType)
    local name = configData.name
    table.insert(tmp, {
      itemType = reward.itemType,
      itemId = reward.itemId,
      img_icon = configData.icon,
      quality = configData.quality,
      name = name,
      txt_desc = isLock and L_WordsTpl:getValue("ui_moduleCanteenFree_03", {
        [0] = dropUnlockLevel
      }) or _productsCollectionTypeTpl:getTypeName(tpl_dropType),
      go_lock = isLock,
      unLockLevel = dropUnlockLevel,
      sortId = productId,
      lockStatus = isLock and 1 or 0,
      go_rare = isShowRare,
      img_rare = _productsCollectionTypeTpl:getIcon(tpl_dropType),
      go_mask = isLock and isShowRare,
      canvasGroup = isLock and 0.5 or 1
    })
  end
  table.sort(tmp, function(a, b)
    if a.lockStatus == b.lockStatus then
      if a.unLockLevel == b.unLockLevel then
        return a.sortId < b.sortId
      else
        return a.unLockLevel < b.unLockLevel
      end
    else
      return a.lockStatus < b.lockStatus
    end
  end)
  for i = 1, #tmp do
    tmp[i].go_line = i % 2 == 0
  end
  self.bind.scrollList_preview:clear()
  self.bind.scrollList_preview:insert_array(tmp)
end

function this:initOutputList(needSort)
  if needSort then
    self.bind.scrollList_output:clear()
  end
  local rewardList = L_CollectionManager:getCollectCommonItemRewardList(self._collectionGuid, needSort)
  self.bind.go_full = #rewardList >= L_CollectionManager:getMaxCollectionLimit()
  local lineNum = math.ceil(#rewardList / 6)
  lineNum = math.max(4, lineNum)
  self.bindComponents.verGridView_output.disableScroll = lineNum <= 4
  local oldRewardCount = #self.modules.scrollList_output
  local newRewardCount = math.min(L_CollectionManager:getMaxCollectionLimit(), lineNum * 6)
  local rewardCache = {}
  local rewardDic = {}
  local rewardTable = {}
  for i, v in ipairs(self.modules.scrollList_output) do
    if not table.isEmpty(v.bind.reward) then
      rewardCache[v.bind.product_id] = 1
      table.insert(rewardTable, v.bind.product_id)
    end
  end
  for i, v in ipairs(rewardList) do
    if rewardDic[v.product_id] == nil then
      rewardDic[v.product_id] = L_Struct.getQueue()
    end
    rewardDic[v.product_id]:enQueue(v)
  end
  local isSame = oldRewardCount == newRewardCount
  if isSame then
    local id_map = {}
    for i, v in ipairs(self.modules.scrollList_output) do
      local reward, findIndex
      local needShowAni = false
      if rewardDic[v.bind.product_id] and rewardDic[v.bind.product_id]:getLength() > 0 then
        local length = rewardDic[v.bind.product_id]:getLength()
        id_map[v.bind.product_id] = 1
        for n = 1, length do
          reward = rewardDic[v.bind.product_id]:deQueue()
          self.modules.scrollList_output[i + n - 1]:setItem(reward, needShowAni, i + n - 1)
        end
      elseif not rewardCache[v.bind.product_id] then
        for _, k in ipairs(rewardList) do
          if id_map[k.product_id] ~= 1 then
            reward = k
            findIndex = i
            v:setItem(reward, true, findIndex)
            id_map[k.product_id] = 1
            break
          end
        end
      end
    end
  else
    local tmp = {}
    local max = math.min(lineNum * 6, L_CollectionManager:getMaxCollectionLimit())
    if 1 < #rewardTable then
      local index = 0
      for i, v in ipairs(rewardTable) do
        if rewardCache[v] and rewardDic[v]:getLength() > 0 then
          local length = rewardDic[v]:getLength()
          for i = 1, length do
            index = index + 1
            table.insert(tmp, {
              index = index,
              product_id = v,
              reward = rewardDic[v]:deQueue()
            })
          end
        end
      end
      for i, v in ipairs(rewardList) do
        if rewardCache[v.product_id] == nil then
          index = index + 1
          table.insert(tmp, {
            index = index,
            product_id = v.product_id,
            reward = v
          })
        end
      end
      for i = index + 1, max do
        local reward
        table.insert(tmp, {
          index = i,
          product_id = 0,
          reward = reward
        })
      end
    else
      for i = 1, max do
        local reward
        if i <= #rewardList then
          reward = rewardList[i]
        end
        table.insert(tmp, {
          index = i,
          product_id = reward and reward.product_id or 0,
          reward = reward
        })
      end
    end
    self.bind.scrollList_output:clear()
    self.bind.scrollList_output:insert_array(tmp)
  end
  local hasReward = not table.isEmpty(rewardList)
  self.bind.go_btn_collect = hasReward
end

function this:openTickTimer()
  local serverData = L_CollectionStore:getCollection(self._collectionGuid)
  local pet = L_PetStore:getPetItem(serverData.pet_guid)
  if table.isEmpty(pet) then
    return
  end
  local endTime = L_SatietyStore:calculateSatietyTimeStamp(pet)
  self.bind.go_pause = false
  local func = function()
    local nowTime = L_TimeUtil.getServerTime()
    local leftTime = endTime - nowTime
    self.bind.go_running = 0 < leftTime
    if 0 < leftTime then
      self.bind.txt_time_running = L_TimeUtil.secondToLangString(leftTime)
    else
      local serverData = L_CollectionStore:getCollection(self._collectionGuid)
      local isWorkPause = L_SatietyStore:isWorkPause(serverData.pet_guid)
      if isWorkPause then
        local pet = L_PetStore:getPetItem(serverData.pet_guid)
        L_TimerManager:stopTimer(self, "timeTick")
        L_TimerManager:stopTimer(self, "reqCollect_timeTick")
        self.bind.go_running = false
        self.bind.go_pause = true
        self.bind.txt_pause = pet:isInCanteen() and L_WordsTpl:getValue("notice_pageCollection_03") or L_WordsTpl:getValue("notice_pageCollection_04")
      end
      L_TimerManager:clearTimer(self)
    end
  end
  L_TimerManager:newOrResetTimer(self, "timeTick", func, 1, -1)
  func()
end

function this:refreshPauseInfo()
  local serverData = L_CollectionStore:getCollection(self._collectionGuid)
  local isWorkPause = L_SatietyStore:isWorkPause(serverData.pet_guid)
  if isWorkPause then
    local pet = L_PetStore:getPetItem(serverData.pet_guid)
    L_TimerManager:stopTimer(self, "timeTick")
    L_TimerManager:stopTimer(self, "reqCollect_timeTick")
    self.bind.go_running = false
    self.bind.go_pause = true
    self.bind.txt_pause = pet:isInCanteen() and L_WordsTpl:getValue("notice_pageCollection_03") or L_WordsTpl:getValue("notice_pageCollection_04")
  else
    self:openTickTimer()
  end
end

function this:onEvent_refreshPet()
  self:initPage()
end

function this:onEvent_refreshCollection()
  self:initPage()
end

function this:onEvent_updateCollection(updateList)
  self:refreshPauseInfo()
  self:initOutputList()
end

function this:checkCollect()
  local serverData = L_CollectionStore:getCollection(self._collectionGuid)
  local tpl_building = _homeBuildingCollectionTpl:getTplById(serverData.build_id)
  local needPet = _homeBuildingCollectionTpl:getIsNeedPet(tpl_building)
  if needPet and math.isEmpty(serverData.pet_guid) then
    L_FlyMsgManager:showNormalMsgByKey("notice_pageCollection_05")
    return
  end
  self:reqStartCollect()
end

function this:reqStartCollect()
  L_CollectionManager:reqStartCollect(self._collectionGuid, 1, function()
    L_UI:close(self.pageName)
  end)
end

function this:loadVirtualCamera(entity)
  local serverData = L_CollectionStore:getCollection(self._collectionGuid)
  local cameraController = L_CameraManager:switchToCollection()
  cameraController:setData(entity, serverData.build_id)
end

function this:unloadVirtualCamera()
  local blend = L_CameraManager:getBlendStyle(L_Const.blendStyleMode.custom)
  blend.time = 1000
  L_CameraManager:revertCamController(blend)
end

function this:closeCheck()
  L_UI:close(self.pageName)
end

function this:refreshProperty()
  local serverData = L_CollectionStore:getCollection(self._collectionGuid)
  if table.isEmpty(serverData) then
    return
  end
  self.modules.module_homeProperty:setCollection(self._collectionGuid)
end

function this:escHandle()
  self:closeCheck()
end

function this:registerConditionsOfUnlockMaxWorkingNumOfCollectionBuildingAtSameTime()
  local allConditionGroup = _homeCollectionWorkLimitTpl:getAllConditionGroup()
  self.conditionNodeList = {}
  for _, conditionGroup in pairs(allConditionGroup) do
    local conditionNode = L_ConditionManager:registGroup("pageCollection", conditionGroup, self.onConditionNodeStateChanged, self)
    table.insert(self.conditionNodeList, conditionNode)
  end
end

function this:unregisterConditionsOfUnlockMaxWorkingNumOfCollectionBuildingAtSameTime()
  for _, conditionNode in pairs(self.conditionNodeList) do
    L_ConditionManager:unRegist(conditionNode, "pageCollection")
  end
end

function this:onConditionNodeStateChanged()
  self:refreshCollectionBuildingWorkLimitPart()
end

function this:refreshCollectionBuildingWorkLimitPart()
  local curWorkingNum = AzurWorld.HomeMgr:GetCurWorkingNumOfCollectionBuilding()
  local maxWorkingNum = _homeCollectionWorkLimitTpl:getCurMaxWorkingNum()
  local limit = L_WordsTpl:getValue("notice_home_collectionbuilding_limit")
  limit = L_GameUtil.removeXmlTags(limit, "color")
  self.bind.txt_workLimit = L_Lang:get(limit, {
    [0] = curWorkingNum,
    [1] = maxWorkingNum
  })
end

return this
