local this = class("moduleHomeCenterCollection", require("ui.pages.home.homeCenter.moduleHomeCenterToggleModule"))
this:importPartialClass(require("ui.pages.home.homeCenter.moduleHomeCenterCollection.moduleHomeCenterCollectionInfo"))
local collectionText = {
  stopTitle = "notice_pageCollection_01",
  stopContent = "notice_pageCollection_02",
  noOutput = "notice_moduleHomeCenterCollection_01",
  notBuilt = "notice_moduleHomeCenterCollection_02"
}

function this.bind()
  return {
    module_tabList = {
      moduleName = "modulePages/tabList/modulePageProductTabList"
    },
    listToggle = true,
    go_free = false,
    txt_time_free = nil,
    go_working = false,
    go_running = false,
    txt_time_running = nil,
    go_finish = false,
    go_collect = false,
    go_pause = true,
    txt_pause = nil,
    go_full = false,
    scrollList_collectionItem = {
      moduleName = "pages/collection/cellCollectionOutput"
    },
    scrollList_preview = {
      moduleName = "pages/collection/cellCollectionPreview"
    },
    module_top = {
      moduleName = "pages/home/moduleHomeBuildingTop"
    },
    module_petInfo = {
      moduleName = "pages/product/modulePetInfo"
    },
    infoToggle = false,
    emptyTips = "",
    collectionList = {
      moduleName = "pages/home/homeCenter/moduleHomeCenterCollection/cellHomeCenterCollection"
    },
    dragCollection = {
      moduleName = "pages/home/homeCenter/moduleHomeCenterCollection/cellHomeCenterCollection"
    },
    enabled_scrollBag = true,
    infoToggle_show = false,
    btn_blank = false,
    txt_workLimit = ""
  }
end

function this.methods()
  return {
    onClick_collect = function(self)
      L_CollectionManager:reqCollectReward(self._collectionGuid, self._buildingGuid, function()
        self:initRightShow(true)
      end)
    end,
    onClick_collectAll = function(self)
      local canCollectAll, guidList = L_CollectionManager:judgeCanCollectReward()
      if canCollectAll then
        L_CollectionManager:reqCollectAllReward(guidList, self._buildingGuid, function()
          self:initRightShow(true)
        end)
      else
        L_FlyMsgManager:showNormalMsgByKey(collectionText.noOutput)
      end
    end,
    onClick_closeBlank = function(self)
      self:refreshUI()
    end,
    collectionList = {
      onClick_choose = function(self, bind, position)
        if self._dragStart then
          return
        end
        if table.isEmpty(bind.serverData) then
          L_FlyMsgManager:showNormalMsgByKey(collectionText.notBuilt, {
            [0] = bind.tagName
          })
        else
          self._collectionGuid = bind.collectionGuid
          L_UI:open("pageCollection", {
            guid = bind.collectionGuid
          }, function()
            self:refreshUI()
          end)
          goto lbl_42
          self._collectionGuid = bind.collectionGuid
          self:refreshView()
          self.bind.btn_blank = true
          self:checkBorderPos(position)
          self:req_initCollection(bind)
        end
        ::lbl_42::
      end
    }
  }
end

local homeCollectionWorldTpl = L_GameTpl:getHomeCollectionWorldTpl()
local homeCollectionWorkLimitTpl = L_GameTpl:getHomeCollectionWorkLimitTpl()
local screenPosToUI = Unity.RectTransformUtility.ScreenPointToLocalPointInRectangle
local C_HomeManager = AzurWorld.HomeMgr

function this:open()
  L_CollectionStore:listenCallFunc(L_CollectionStore.event.updateCollection, self.onEvent_updateCollection, self)
  L_PetStore:listenCallFunc(L_PetStore.event.refreshBuildingPet, self.onEvent_refreshPet, self)
  self:registerConditionsOfUnlockMaxWorkingNumOfCollectionBuildingAtSameTime()
end

function this:close()
  L_TimerManager:clearTimer(self)
  L_CollectionStore:unListenCallFunc(L_CollectionStore.event.updateCollection, self.onEvent_updateCollection)
  L_PetStore:unListenCallFunc(L_PetStore.event.refreshBuildingPet, self.onEvent_refreshPet)
  self:unregisterConditionsOfUnlockMaxWorkingNumOfCollectionBuildingAtSameTime()
end

function this:refreshData()
  if not self._buildingGuid then
    self._buildingGuid = 0
    self._selectType = 201
    self:initCollectionData()
  end
end

function this:refreshUI()
  self.bind.btn_blank = false
  self.bind.infoToggle_show = false
  self:refreshView(true)
  self:endDrag()
  self:refreshWorkLimitPart()
end

function this:escHandle()
  if self.bind.infoToggle_show then
    self:refreshUI()
    return false
  end
  return true
end

function this:refreshView(isSetFalse)
  if isSetFalse then
    for i, v in pairs(self.bind.collectionList) do
      self.bind.collectionList:change(i, {isChoose = false})
    end
  else
    for i, v in pairs(self.bind.collectionList) do
      if self._collectionGuid == v.collectionGuid then
        self.bind.collectionList:change(i, {isChoose = true})
      else
        self.bind.collectionList:change(i, {isChoose = false})
      end
    end
  end
end

function this:initCollectionData()
  self:initMenu()
  self:updateMenuType(true)
end

function this:initMenu()
  self.allData = homeCollectionWorldTpl:getAllTplByType()
  local rawData = {}
  for i, v in pairs(self.allData) do
    table.insert(rawData, {type = i})
  end
  table.sort(rawData, function(a, b)
    return a.type < b.type
  end)
  self:refreshBuildingInfo()
  local tabList = {201}
  local selectIndex = 1
  for i, v in ipairs(rawData) do
    if v.type ~= 0 then
      table.insert(tabList, tonumber("400" .. v.type))
    end
  end
  self._selectType = self._selectType or rawData[1].type
  local tabParam = {
    idList = tabList,
    selectId = selectIndex,
    tabType = "building",
    callback = function(tab)
      local id = tab % 1000
      if id == self._selectType then
        return
      end
      self._selectType = id
      self:updateMenuType(true)
    end
  }
  self.modules.module_tabList:setData(tabParam)
end

local collectionSortFunction = function(a, b)
  local serverA = not table.isEmpty(a.serverData)
  local serverB = not table.isEmpty(b.serverData)
  if serverA ~= serverB then
    return serverA
  end
  local customA = a.buildPos or math.maxinteger
  local customB = b.buildPos or math.maxinteger
  if customA ~= customB then
    return customA < customB
  end
  return a.defaultIndex < b.defaultIndex
end

function this:refreshBuildingInfo()
  local homeHubWorkingBuildingInfoList = L_HomeStore:getHomeHubWorkingBuildingInfoListByTabType(L_Const.HomeHubTabType.HHTT_COLLECT)
  self._buidingMap = self._buidingMap or {}
  for i, v in ipairs(homeHubWorkingBuildingInfoList) do
    local csHomeBuildData = L_HomeStore:getCsHomeCollectBuildDataByGuid(v.guid)
    if csHomeBuildData then
      local guid = csHomeBuildData.collect.Guid
      self._buidingMap[guid] = v
    end
  end
end

function this:updateMenuType(refresh)
  if refresh then
    local data = self.allData[self._selectType] or homeCollectionWorldTpl:getAllTpl()
    self.bind.infoToggle_show = false
    self.bind.btn_blank = false
    local sortedData = {}
    local defaultIndex = 0
    for i, v in ipairs(data) do
      local guid = homeCollectionWorldTpl:getId(v)
      local serverIndex = self._buidingMap[guid] and self._buidingMap[guid].index
      local isBuffBuilding = homeCollectionWorldTpl:getType(v) == 2
      if not isBuffBuilding then
        defaultIndex = defaultIndex + 1
        sortedData[defaultIndex] = {
          data = v,
          buildPos = serverIndex or nil,
          defaultIndex = defaultIndex,
          collectionGuid = guid,
          opacity = defaultIndex == self._holdId and 0 or 1,
          serverData = L_CollectionStore:getCollection(guid) or {},
          isChoose = false,
          tagName = homeCollectionWorldTpl:getName(v)
        }
      end
    end
    table.sort(sortedData, collectionSortFunction)
    self._sortedData = sortedData
    self._sortedBuildPos = {}
    for i, v in ipairs(self._sortedData) do
      self._sortedBuildPos[i] = v.buildPos
      v.buildPos = nil
    end
  end
  if 0 < #self._sortedData then
    self._collectionGuid = self._collectionGuid or homeCollectionWorldTpl:getId(self._sortedData[1])
    self.bind.listToggle = true
  else
    self.bind.listToggle = false
  end
  if refresh then
    local tmp = clone(self._sortedData)
    for i, v in ipairs(tmp) do
      v.index = i
    end
    self.bind.collectionList:clear()
    self.bind.collectionList:insert_array(tmp)
  else
    for i, collection in ipairs(self.bind.collectionList:getItemCls()) do
      collection:setCollectionData(self._sortedData[i], i)
      collection.bind.opacity = i == self._holdId and 0 or 1
    end
  end
end

function this:checkBorderPos(position)
  local screenPos_cell = C_CameraManager.uiCamera:WorldToScreenPoint(position)
  local parent = self.bindComponents.rect_board
  local _, uiPos = screenPosToUI(parent, L_Vector3.new(screenPos_cell.x, screenPos_cell.y), C_CameraManager.uiCamera)
  local info = self.bindComponents.infoTrans
  if uiPos.x - 170 > 0 then
    uiPos.x = uiPos.x - 475
  else
    uiPos.x = uiPos.x + 475
  end
  uiPos.y = info.anchoredPosition.y
  L_Vector3.setAnchored(info, uiPos)
end

function this:req_initCollection(info)
  if table.isEmpty(info.serverData) then
    self.bind.infoToggle_show = true
    self.bind.emptyTips = L_WordsTpl:getValue(collectionText.notBuilt, {
      [0] = info.tagName
    })
    self:initRightShow(true)
    return
  end
  self.bind.infoToggle_show = true
  self:initRightShow(true)
end

function this:registerConditionsOfUnlockMaxWorkingNumOfCollectionBuildingAtSameTime()
  local allConditionGroup = homeCollectionWorkLimitTpl:getAllConditionGroup()
  self.conditionNodeList = {}
  for _, conditionGroup in pairs(allConditionGroup) do
    local conditionNode = L_ConditionManager:registGroup("moduleHomeCenterCollection", conditionGroup, self.refreshWorkLimitPart, self)
    table.insert(self.conditionNodeList, conditionNode)
  end
  L_CollectionStore:listenCallFunc(L_CollectionStore.event.updateCollection, self.refreshWorkLimitPart, self)
end

function this:unregisterConditionsOfUnlockMaxWorkingNumOfCollectionBuildingAtSameTime()
  for _, conditionNode in pairs(self.conditionNodeList) do
    L_ConditionManager:unRegist(conditionNode, "moduleHomeCenterCollection")
  end
  L_CollectionStore:unListenCallFunc(L_CollectionStore.event.updateCollection, self.refreshWorkLimitPart, self)
end

function this:refreshWorkLimitPart()
  local curWorkingNum = AzurWorld.HomeMgr:GetCurWorkingNumOfCollectionBuilding()
  local maxWorkingNum = homeCollectionWorkLimitTpl:getCurMaxWorkingNum()
  self.bind.txt_workLimit = L_Lang:get(L_WordsTpl:getValue("notice_home_collectionbuilding_limit"), {
    [0] = curWorkingNum,
    [1] = maxWorkingNum
  })
end

function this:changeIndex(oldIndex, targetIndex)
  if targetIndex == oldIndex then
    return
  end
  local dir = oldIndex < targetIndex and 1 or -1
  if self._sortedBuildPos[math.max(oldIndex, targetIndex)] then
    L_HomeStore:reqChangeHomeHubBuildingPos(L_Const.HomeHubTabType.HHTT_COLLECT, self._sortedBuildPos[oldIndex], self._sortedBuildPos[targetIndex])
  end
  local tmp = table.remove(self._sortedData, oldIndex)
  table.insert(self._sortedData, targetIndex, tmp)
  for i = oldIndex, targetIndex, dir do
    local guid = self._sortedData[i].collectionGuid
    local sourcePos = self._buidingMap[guid] and self._buidingMap[guid].index
    local targetPos = self._sortedBuildPos[i]
    if sourcePos and targetPos then
      self._buidingMap[guid].index = targetPos
    end
  end
end

function this:setDragProxy(index)
  local data = self._sortedData[index]
  self.modules.dragCollection:setCollectionData(data, index)
end

function this:show()
  this.super.show(self)
  self:configDrag("+")
end

function this:hide()
  this.super.hide(self)
  self:configDrag("-")
end

function this:configDrag(operator)
  self.onUITouchHandle = self.onUITouchHandle or L_CommonUtil.handle(self.onUI_TouchHandle, self)
  self.onUILongTapEndHandle = self.onUILongTapEndHandle or L_CommonUtil.handle(self.onUI_longTapEndHandle, self)
  self.onUIDragHandle = self.onUIDragHandle or L_CommonUtil.handle(self.onUI_dragHandle, self)
  self.onUIDragEndHandle = self.onUIDragEndHandle or L_CommonUtil.handle(self.onUI_dragEndHandle, self)
  C_ScreenTouch.OnUI_Touch(operator, self.onUITouchHandle)
  C_ScreenTouch.OnUI_LongTapEnd(operator, self.onUILongTapEndHandle)
  C_ScreenTouch.OnUI_Drag(operator, self.onUIDragHandle)
  C_ScreenTouch.OnUI_DragEnd(operator, self.onUIDragEndHandle)
end

function this:endDrag()
  self._holdId = nil
  self._dragStart = false
  if not self.isBind then
    return
  end
  self:updateMenuType(false)
  L_TimerManager:stopTimer(self, "timerDrag")
  self.modules.dragCollection:getRaycastGo():ActiveTrans(false)
  self.bind.enabled_scrollBag = true
end

function this:getHoldInfo(go)
  for i, collection in ipairs(self.bind.collectionList:getItemCls()) do
    if collection:getRaycastGo() == go and not table.isEmpty(collection.bind.serverData) then
      return i
    end
  end
  return nil
end

function this:onUI_longTapEndHandle(gesture)
  self:endDrag()
end

function this:onUI_TouchHandle(gesture)
  if self._dragStart then
    return
  end
  local go = gesture.go
  local holdId = self:getHoldInfo(go)
  if not holdId then
    return
  end
  self._holdId = holdId
  local touchPos = L_Vector3.screenToLocalInRectangle(self.bindComponents.rect_board, gesture.position)
  L_FlyMsgManager:startLongPress(gesture, 0.5, function()
    if not self.isBind or not self._holdId then
      return
    end
    self:setDragProxy(self._holdId)
    self.modules.dragCollection:getRaycastGo():ActiveTrans(true)
    self.bind.enabled_scrollBag = false
    L_Vector3.setAnchored(self.modules.dragCollection.bindComponents.collectionTrans, touchPos)
    self:updateMenuType(false)
    self._dragStart = true
    self._dragEdge = nil
    if not self._dragFunc then
      function self._dragFunc()
        if not self._dragEdge then
          return
        end
        local distance = self._dragEdge * C_Time.unscaledDeltaTime * 500
        self.bindComponents.collectionView:ScrollByDistance(distance)
      end
    end
    L_TimerManager:newOrResetTimer(self, "timerDrag", self._dragFunc, 0, -1, false)
  end)
end

function this:onUI_dragHandle(gesture)
  if not self._dragStart then
    return
  end
  local touchPos = L_Vector3.screenToLocalInRectangle(self.bindComponents.rect_board, gesture.position)
  L_Vector3.setAnchored(self.modules.dragCollection.bindComponents.collectionTrans, touchPos)
  local rect = self.bindComponents.rect_board.rect
  if touchPos.y > rect.y + rect.height * 0.9 then
    self._dragEdge = -1
  elseif touchPos.y < rect.y + rect.height * 0.2 then
    self._dragEdge = 1
  else
    self._dragEdge = nil
  end
end

function this:onUI_dragEndHandle(gesture)
  if not self._dragStart then
    return
  end
  local go = gesture:GetCurrentFirstPickedUIElement()
  local endId = self:getHoldInfo(go)
  if endId and endId ~= self._holdId then
    self:changeIndex(self._holdId, endId)
  end
  self:endDrag()
end

return this
