local this = class("moduleSelectPet", G_UIModuleBase)
local PageCount = 30
local isPc = L_DeviceTpl:getIsPc()
local isMobile = L_DeviceTpl:getIsMobile()
local PropertyModulePosY = L_DeviceTpl:getIsPc() and -160 or -20
local PropertyModuleArrowPosY = -9.8

function this.bind()
  return {
    go_expand = false,
    go_shrink = false,
    go_switchCam = false,
    isOn_listEmpty_shrink = false,
    list_pet_shrink = {
      moduleName = "pages/formation/formationModule/cellPixelPetFormation"
    },
    module_sortFilter_shrink = L_Const.ModuleInfo.SortFilterModule,
    go_boxInfo_shrink = false,
    module_petBoxSortFilter = {
      moduleName = "modulePages/sortFilter/modulePetBoxFilter"
    },
    list_pet_expand = {
      moduleName = "pages/formation/formationModule/cellPixelPetFormation"
    },
    txt_boxName_expand = nil,
    txt_boxIndex_expand = nil,
    go_changePageTab = false,
    go_lastBtn = false,
    go_nextBtn = false,
    module_pageTabSlider = {
      moduleName = "modulePages/modulePageTabSlider"
    },
    module_sortFilter_expand = L_Const.ModuleInfo.SortFilterModule,
    module_formationPetProperty = {
      moduleName = "pages/formation/formationModule/moduleFormationPetProperty"
    },
    localPosition_propertyModule = nil,
    localPosition_propertyModuleArrow = nil
  }
end

function this.methods()
  return {
    onClick_lastPage = function(self)
      self:changePageIndex(-1)
    end,
    onClick_nextPage = function(self)
      self:changePageIndex(1)
    end,
    onClick_shrink = function(self)
      if self._isPlayingVFX then
        return
      end
      self:playShrinkVFX()
      self:refreshContent()
    end,
    onClick_expand = function(self)
      if self._isPlayingVFX then
        return
      end
      self:playExpandVFX()
      self:refreshContent()
    end,
    onClick_closeExpand = function(self)
      if self._isPlayingVFX then
        return
      end
      self:playShrinkVFX()
      self:refreshContent()
    end,
    onClick_btnBg = function(self)
      self:escHandle()
    end,
    onClick_cameraSwitch = function(self)
      self:petCameraSwitch()
    end,
    onClick_detail = function(self)
      if math.isEmpty(self.selPetID) then
        L_FlyMsgManager:showNormalMsg("\232\175\183\229\133\136\233\128\137\228\184\173\232\167\146\232\137\178/\229\165\135\230\179\162")
        return
      end
      L_UI:open("pagePet", {
        petId = self.selPetID,
        callBack = function()
          Timer.once(0.2, function()
            self.methods.onClick_expand(self)
          end)
        end
      })
    end
  }
end

function this:open()
  self._petPropertyModule = self.modules.module_formationPetProperty
  self._selectPetHandler = handler(self, self.selectPet)
  self._onPointEnterPetCellHandler = handler(self, self.onPointEnterPetCell)
  self._onPointExitPetCellHandler = handler(self, self.onPointExitPetCell)
end

function this:close(options)
  self:configTouch("-")
  L_TimerManager:clearTimer(self)
end

function this:initModule(param)
  self._param = param or {}
  self._petBoxIndex = param.defaultSelectBoxIndex
  self.cellType = param.cellType
  self.editMode = param.editMode or false
  self:initSortFilterModule()
  self.bind.go_shrink = false
  self:playShrinkVFX()
  self:initPetList()
  self:refreshContent()
  self._petPropertyModule:showModuleInfo(false)
end

function this:initSortFilterModule()
  if L_FormationManager:getRuntimeFormationIndex() ~= nil and self._lastEditFormationIndex == L_FormationManager:getRuntimeFormationIndex() then
    return
  end
  self._lastEditFormationIndex = L_FormationManager:getRuntimeFormationIndex()
  self._petSortFilter = L_SortFilterManager:createSortFilter(self._param.systemId, function()
    self._petPageIndex = 1
    self:initPetList()
    self:refreshContent()
  end, function()
    self._petPageIndex = 1
    self:initPetList()
    self:refreshContent()
  end)
end

function this:refreshContent()
  if self._isExpand then
    self._petSortFilter:bindModule(self.modules.module_sortFilter_expand)
    self:refreshCurPagePet_expand()
    self:refreshPageTabInfo(true)
  else
    self._petSortFilter:bindModule(self.modules.module_sortFilter_shrink)
    self:refreshCurPagePet_shrink()
    self.bind.go_boxInfo_shrink = self._isPetBoxMode
    if self._isPetBoxMode then
      self:initPetBoxFilterModule()
    end
  end
  self:configTouch(self._isExpand and "-" or "+")
end

function this:initPetList()
  self._isPetBoxMode = self._petSortFilter.filterKeyDic[L_SortFilterConst.FilterType.QiBoBoxMode] == nil
  if not self._isPetBoxMode then
    local allPet = L_PetStore:getPetList()
    self._petTotalDataList = {}
    for i, pet in pairs(allPet) do
      table.insert(self._petTotalDataList, {
        itemType = L_Const.resType.pet,
        itemId = pet.id,
        guid = pet.guid
      })
    end
    self._petSortFilter:sortFilterList(self._petTotalDataList)
  end
end

function this:changePageIndex(delta)
  if self._isPetBoxMode then
    self._petBoxIndex = math.clamp(self._petBoxIndex + delta, 1, L_PetStore:getPetBoxNum())
  else
    self._petPageIndex = math.clamp(self._petPageIndex + delta, 1, self._petTotalPageNum)
  end
  self:refreshCurPagePet_expand()
  self:refreshPageTabInfo()
end

function this:refreshCurPagePet_expand()
  self:moveToPage()
  local curPageData = {}
  if self._isPetBoxMode then
    self._petBoxIndex = self._petBoxIndex or 1
    local boxData = L_PetStore:getPetBoxList(self._petBoxIndex)
    local temp = {}
    for i, guid in pairs(boxData) do
      if not math.isEmpty(guid) then
        local petData = L_PetStore:getPetItem(guid)
        table.insert(temp, {
          itemType = L_Const.resType.pet,
          itemId = petData.id,
          guid = guid,
          type = self.cellType or L_Const.cellIconUnitType.selectPet,
          callback = self._selectPetHandler
        })
      end
    end
    self._petSortFilter:filterList(temp)
    for i = 1, PageCount do
      table.insert(curPageData, {
        itemType = 0,
        itemId = 0,
        guid = 0,
        callback = nil
      })
    end
    for i, cell in pairs(temp) do
      local pet = L_PetStore:getPetItem(cell.guid)
      curPageData[pet.box_id % 100] = cell
    end
  else
    self._petPageIndex = self._petPageIndex or 1
    for i = (self._petPageIndex - 1) * PageCount + 1, self._petPageIndex * PageCount do
      if not self._petTotalDataList[i] then
        break
      end
      table.insert(curPageData, {
        guid = self._petTotalDataList[i].guid,
        callback = self._selectPetHandler
      })
    end
  end
  self:initBoxInfo_expand()
  if #self.bind.list_pet_expand == #curPageData then
    for i, v in pairs(curPageData) do
      self.bind.list_pet_expand:change(i, v)
    end
  else
    self.bind.list_pet_expand:clear()
    self.bind.list_pet_expand:insert_array(curPageData)
  end
end

function this:initBoxInfo_expand()
  self.bind.txt_boxName_expand = self._isPetBoxMode and L_PetStore:getPetBoxName(self._petBoxIndex) or L_WordsTpl:getValue("ui_moduleSelectPet")
  self.bind.txt_boxIndex_expand = self._isPetBoxMode and string.format("%02d", self._petBoxIndex) or ""
end

function this:refreshCurPagePet_shrink()
  if self.editMode then
    self:checkHasPet()
  end
  if self._isPetBoxMode then
    self:moveToPage()
  end
  local curPageData = {}
  if self._isPetBoxMode then
    self._petBoxIndex = self._petBoxIndex or 1
    local boxData = L_PetStore:getPetBoxList(self._petBoxIndex)
    local temp = {}
    for i, guid in pairs(boxData) do
      if not math.isEmpty(guid) then
        local petData = L_PetStore:getPetItem(guid)
        table.insert(temp, {
          itemType = L_Const.resType.pet,
          itemId = petData.id,
          type = self.cellType or L_Const.cellIconUnitType.selectPet,
          guid = guid,
          callback = self._selectPetHandler,
          pointEnterCallback = self._onPointEnterPetCellHandler,
          pointExitCallback = self._onPointExitPetCellHandler
        })
      end
    end
    self._petSortFilter:sortFilterList(temp)
    for i = 1, PageCount do
      table.insert(curPageData, {
        itemType = 0,
        itemId = 0,
        guid = 0,
        callback = nil
      })
    end
    for i, cell in pairs(temp) do
      local pet = L_PetStore:getPetItem(cell.guid)
      curPageData[pet.box_id % 100] = cell
    end
  else
    for i, v in ipairs(self._petTotalDataList) do
      table.insert(curPageData, {
        guid = v.guid,
        callback = self._selectPetHandler,
        pointEnterCallback = self._onPointEnterPetCellHandler,
        pointExitCallback = self._onPointExitPetCellHandler
      })
    end
  end
  self.bind.isOn_listEmpty_shrink = table.isEmpty(curPageData)
  if #self.bind.list_pet_shrink == #curPageData then
    for i, v in pairs(curPageData) do
      self.bind.list_pet_shrink:change(i, v)
    end
  else
    self.bind.list_pet_shrink:clear()
    self.bind.list_pet_shrink:insert_array(curPageData)
  end
  self.bindComponents.scrollRect_shrink:StopMovement()
  self.bindComponents.scrollRect_shrink:FocusItemIndex(0)
  self:setListSelect(self.selectDic)
end

function this:initPetBoxFilterModule()
  local module_petBoxSortFilter = self.modules.module_petBoxSortFilter
  module_petBoxSortFilter:initModuleByDefaultIndex(self._petBoxIndex, function(selectIndex)
    self._petBoxIndex = selectIndex
    self:refreshCurPagePet_shrink()
  end)
end

function this:refreshPageTabInfo(isInit)
  local totalPage, curPage
  if self._isPetBoxMode then
    totalPage = L_PetStore:getPetBoxNum()
    curPage = self._petBoxIndex
  else
    totalPage = math.ceil(#self._petTotalDataList / PageCount)
    curPage = self._petPageIndex
  end
  local needShowTab = 1 < totalPage
  self.bind.go_changePageTab = needShowTab
  if needShowTab then
    self.bind.go_lastBtn = 1 < curPage
    self.bind.go_nextBtn = totalPage > curPage
    local modulePageTabSlider = self.modules.module_pageTabSlider
    modulePageTabSlider:setPageIndex(curPage, totalPage)
  end
end

function this:selectPet(cell)
  self:emit("onClick_selectPet", cell.bind.guid)
  self.selPetID = cell.bind.guid
  if not self.editMode then
    return
  end
  local petPosIdx = L_FormationStore:getPetPlaceInTeam(L_FormationManager:getRuntimeFormationType(), L_FormationManager:getRuntimeFormationIndex(), cell.bind.guid)
  if petPosIdx == L_FormationManager:getFocusIndex() then
    self.bind.go_switchCam = false
    if self.parent and self.parent.resetPetCamera then
      self.parent:resetPetCamera()
    end
  else
    self.bind.go_switchCam = false
  end
end

function this:moveToPage()
  if math.isEmpty(self._moveToId) then
    return
  end
  if self._isPetBoxMode then
    self._petBoxIndex = math.floor(L_PetStore:getPetItem(self._moveToId).box_id / 100)
  else
    for i, v in ipairs(self._petTotalDataList) do
      if v.guid == self._moveToId then
        self._petPageIndex = math.ceil(i / PageCount)
        break
      end
    end
  end
  self._moveToId = nil
end

function this:escHandle()
  if self._isPlayingVFX then
    return true
  end
  if self._isExpand then
    self:playShrinkVFX()
    self:refreshContent()
    return true
  end
end

function this:setListSelect(selectDic)
  self.selectDic = selectDic or {}
  for i, v in pairs(self.modules.list_pet_shrink) do
    local cell = v
    local petParams = self.selectDic[cell.bind.guid]
    cell:setSelect((petParams and petParams.isSelect) == true)
    cell:setPosIndex(petParams and petParams.index)
  end
  for i, v in pairs(self.modules.list_pet_expand) do
    local cell = v
    local petParams = self.selectDic[cell.bind.guid]
    cell:setSelect((petParams and petParams.isSelect) == true)
    cell:setPosIndex(petParams and petParams.index)
  end
end

function this:petCameraSwitch()
  if self.parent and self.parent.switchPetCamera then
    self.parent:switchPetCamera()
  end
end

function this:checkHasPet()
  local guid = L_FormationStore:getFormationPosPetGuid(L_FormationManager:getRuntimeFormationType(), L_FormationManager:getRuntimeFormationIndex(), L_FormationManager:getFocusIndex())
  if guid and 0 < guid then
    self.bind.go_switchCam = false
  else
    self.bind.go_switchCam = false
  end
end

function this:onPointEnterPetCell(cell)
  if not isPc then
    return
  end
  self:showPetProperty(cell:getRaycastGo(), cell.bind.guid)
end

function this:onPointExitPetCell(cell)
  if not isPc then
    return
  end
  self._petPropertyModule:showModuleInfo(false)
end

function this:configTouch(operator)
  if not isMobile then
    return
  end
  self.onUITouchHandle = self.onUITouchHandle or L_CommonUtil.handle(self.onUI_touchHandle, self)
  self.onUIClickHandle = self.onUIClickHandle or L_CommonUtil.handle(self.onUI_clickHandle, self)
  self.onUIDragEndHandle = self.onUIDragEndHandle or L_CommonUtil.handle(self.onUI_clickHandle, self)
  C_ScreenTouch.OnUI_LongTapEnd(operator, self.onUIClickHandle)
  C_ScreenTouch.OnUI_Touch(operator, self.onUITouchHandle)
  C_ScreenTouch.OnUI_Click(operator, self.onUIClickHandle)
  C_ScreenTouch.OnUI_DragEnd(operator, self.onUIDragEndHandle)
end

function this:onUI_touchHandle(gesture)
  local go = gesture.go
  local holdId = self:getHoldInfo(go)
  if math.isEmpty(holdId) then
    return
  end
  L_FlyMsgManager:startLongPress(gesture, 0.5, function()
    self:showPetProperty(go, holdId)
  end)
end

function this:onUI_clickHandle()
  self._petPropertyModule:showModuleInfo(false)
end

function this:getHoldInfo(go)
  for i, v in ipairs(self.modules.scrollList_pet) do
    local module = v
    if module:getRaycastGo() == go then
      return module.bind.guid
    end
  end
end

function this:showPetProperty(go, guid)
  local targetPosX = self.bindComponents.rect_moduleSelectPet.transform:InverseTransformPoint(go.transform.position).x
  local halfWidth = self.bindComponents.rect_moduleFormationPetProperty.sizeDelta.x * 0.9 * 0.5
  local halfScreenWidth = self.bindComponents.rect_moduleSelectPet.transform.rect.width / 2
  if halfScreenWidth < targetPosX + halfWidth then
    targetPosX = halfScreenWidth - halfWidth
  elseif halfScreenWidth < halfWidth - targetPosX then
    targetPosX = halfWidth - halfScreenWidth
  end
  self.bind.localPosition_propertyModule = L_Vector3.new(targetPosX, PropertyModulePosY, 0)
  self._petPropertyModule:showModuleInfo(true, guid)
  local targetPosArrowX = self._petPropertyModule:getArrowContentRect().transform:InverseTransformPoint(go.transform.position).x
  self.bind.localPosition_propertyModuleArrow = L_Vector3.new(targetPosArrowX, PropertyModuleArrowPosY, 0)
end

function this:playExpandVFX()
  if not self.isBind then
    return
  end
  self.bindComponents.ani_moduleSelectPet:SetBool("Expand", true)
  self.bind.go_expand = true
  self._isExpand = true
  L_TimerManager:newOrResetTimer(self, "playExpandVFX", function()
    self.bind.go_shrink = false
    self.bind.list_pet_shrink:clear()
  end, 0.17)
end

function this:playShrinkVFX()
  if not self.isBind then
    return
  end
  self.bind.go_shrink = true
  self._isExpand = false
  self._isPlayingVFX = true
  self.bindComponents.ani_moduleSelectPet:SetBool("Expand", false)
  L_TimerManager:newOrResetTimer(self, "playShrinkVFX", function()
    self._isPlayingVFX = false
    self.bind.go_expand = false
    self.bind.list_pet_expand:clear()
  end, 0.17)
end

function this:playHideVFX()
  self._isPlayingVFX = true
  self.bindComponents.ani_moduleSelectPet:Play("Hide")
  L_TimerManager:newOrResetTimer(self, "playHideVFX", function()
    self:emit("onVFXPlay_hide")
    self._isPlayingVFX = false
  end, 0.17)
end

return this
