local this = class("pagePetBox", G_UIPageBase)
local _petTpl = L_GameTpl:getPetTpl()

function this:ctor(...)
  this.super.ctor(self, ...)
  self.data = {curIndex = 1}
  self.filterType = {
    [L_PetConst.filterPetBox.level] = "ui_pageHomeCenterPetStationedManage_01",
    [L_PetConst.filterPetBox.grade] = "ui_pageHomeCenterPetStationedManage_02",
    [L_PetConst.filterPetBox.satiety] = "ui_pageHomeCenterPetStationedManage_03",
    [L_PetConst.filterPetBox.labor] = "ui_pageHomeCenterPetStationedManage_04"
  }
end

function this.bind()
  return {
    moveToItemIndex = 0,
    snapToItemIndex = 0,
    loopListBox = {
      moduleName = "pages/pet/cellPetBox"
    },
    loopListBoxPoint = {
      moduleName = "pages/Main/cellActivityPoint"
    },
    modulePetBoxProperty = {
      moduleName = "pages/pet/new/modulePetBoxInfo"
    },
    show_petBoxProperty = false,
    show_empty = false,
    moduleCommonTop = {
      moduleName = "modulePages/moduleCommonTop"
    },
    list_dropdown = {
      moduleName = "modulePages/sortFilter/cellSortFilterDropdown"
    },
    txt_dropDown = "",
    toggleArrow = false,
    dropDownContent = false,
    curBoxIndex = "",
    curBoxName = "",
    img_drag = "",
    edgeLeft_enable = false,
    edgeRight_enable = false,
    listBoxIsDragging = false,
    modulePetRelease = {
      moduleName = "pages/pet/modulePetRelease"
    },
    modulePetReleaseActive = false,
    btnPetFreeActive = true,
    module_pageTabSlider = {
      moduleName = "modulePages/modulePageTabSlider"
    },
    downBgActive = true,
    boxInfoActive = true,
    boxGroupPos = C_Vector2(-1150, 22)
  }
end

function this.methods()
  return {
    onSnapFinished = function(self, index)
      self.realIndex = index
      local snapIndex = index + 1
      local index = self:realSnapToItemIndex(snapIndex)
      self:setPointListActive(index)
    end,
    loopListBox = {
      onClick_Choose = function(self, id)
      end
    },
    onClick_orderPetBoxInfo = function(self)
      local isEmpty = L_PetStore:getPetBoxIsEmpty(self.data.curIndex)
      if isEmpty then
        L_FlyMsgManager:showNormalMsgByKey("notice_pagePetBox_01")
        return
      end
      L_GameUtil.showCommonTip({
        txtTitle = L_WordsTpl:getValue("notice_pagePetBox_02"),
        txtContent = L_WordsTpl:getValue("notice_pagePetBox_03"),
        confirmCallback = function()
          L_PetStore:req_CSProtoOrderPetBoxInfo(self.data.curIndex, function()
            self:refreshCurBox(true)
          end)
        end
      })
    end,
    onClick_changePetBoxName = function(self)
      L_FlyMsgManager:showNormalMsgByKey("notice_pagePetBox_04")
    end,
    onClick_showDropDownContent = function(self)
      self:refreshFilterActive()
      self.bind.dropDownContent = not self.bind.dropDownContent
      self.bind.toggleArrow = not self.bind.toggleArrow
    end,
    onClick_nextBox = function(self)
      self.bind.snapToItemIndex = self.realIndex + 1
      L_AudioUtil.playSound("Play_SFX_System_UI_QiboHouse_Switch")
    end,
    onClick_lastBox = function(self)
      self.bind.snapToItemIndex = self.realIndex - 1
      L_AudioUtil.playSound("Play_SFX_System_UI_QiboHouse_Switch")
    end,
    onClick_PetFree = function(self)
      if not L_SystemUnlockManager:checkAndTip(L_SystemConst.enum.petRelease) then
        return
      end
      L_PetReleaseManager:setIsReleaseMode(true)
      self:setReleaseMode()
      L_FlyMsgManager:showNormalMsg(L_WordsTpl:getValue("ui_pet_release_pet_empty"))
      self.modules.moduleCommonTop:setPageName(L_WordsTpl:getValue("notice_pagePetBox_05"))
    end,
    list_dropdown = {
      onClick_select = function(self, bind)
        self.filter = bind.index
        self.bind.dropDownContent = false
        self.bind.txt_dropDown = bind.type
        self.bind.toggleArrow = false
        self:refreshAllBox()
      end
    },
    onPointEnter_right = function(self)
      if self.bindComponents.rect_drag.gameObject.activeSelf == true then
        self.bind.listBoxIsDragging = false
        self:createAutoDragTimer(1)
      end
    end,
    onPointExit_right = function(self)
      if self.bindComponents.rect_drag.gameObject.activeSelf == true then
        self.bind.listBoxIsDragging = true
        self:killAutoDragTimer()
      end
    end,
    onPointEnter_left = function(self)
      if self.bindComponents.rect_drag.gameObject.activeSelf == true then
        self.bind.listBoxIsDragging = false
        self:createAutoDragTimer(0)
      end
    end,
    onPointExit_left = function(self)
      if self.bindComponents.rect_drag.gameObject.activeSelf == true then
        self.bind.listBoxIsDragging = true
        self:killAutoDragTimer()
      end
    end,
    dropDownContentBgOnClick = function(self)
      self.bind.dropDownContent = false
    end
  }
end

function this:preOpen(options)
  options = options or {}
  if not math.isEmpty(options.defaultPetGuid) then
    local petItem = L_PetStore:getPetItem(options.defaultPetGuid)
    self._defaultBoxIndex = petItem.box_id // 100
    L_PetStore:setCurSelectPetId(options.defaultPetGuid)
  else
    self._defaultBoxIndex = options.defaultBoxIndex
    if self._defaultBoxIndex then
      L_PetStore:setCurSelectPetId(L_PetStore:getPetBoxFirstPet(self._defaultBoxIndex))
    end
  end
  local data = {
    name = L_WordsTpl:getValue("notice_pagePetBox_07"),
    helpBtnBool = false,
    mainBtnBool = true,
    closeCurPage = function()
      self:closePageFunc()
    end,
    helpBtn = function()
    end,
    mainBtn = function()
      L_UI:backToRoot()
    end
  }
  self.modules.moduleCommonTop:initModule(data)
  self.filter = L_PetConst.filterPetBox.grade
  self.realIndex = 0
  self.fingerId = nil
  self.bindComponents.scroll_box.enabled = true
  self.bindComponents.rect_drag.gameObject:ActiveTrans(false)
  self:initModule()
  self.updateTimer = Timer.repeated(0.33, self.onScrollBox, self)
  self:configTouch("+")
  L_ShortCutManager:registerShortCut(self.pageName, C_InputManager_KeyType.ENextBox, function()
    self.bind.snapToItemIndex = self.realIndex + 1
    L_AudioUtil.playSound("Play_SFX_System_UI_QiboHouse_Switch")
  end)
  L_ShortCutManager:registerShortCut(self.pageName, C_InputManager_KeyType.ELastBox, function()
    self.bind.snapToItemIndex = self.realIndex - 1
    L_AudioUtil.playSound("Play_SFX_System_UI_QiboHouse_Switch")
  end)
  L_PetStore:listenCallFunc(L_PetStore.event.setCurPetId, self.onEvent_setCurPetId, self)
  L_PetStore:listenCallFunc(L_PetStore.event.removePet, self.onEvent_removePet, self)
  L_PetStore:listenCallFunc(L_PetStore.event.setSelectReleasePet, self.onEvent_setSelectReleasePet, self)
  self:initSystem()
  self:setReleaseMode()
end

function this:close(options)
  if self.updateTimer then
    Timer.remove(self.updateTimer)
    self.updateTimer = nil
  end
  self:killAutoDragTimer()
  self:configTouch("-")
  L_ShortCutManager:removeShortCut(self.pageName)
  L_PetStore:unListenCallFunc(L_PetStore.event.setCurPetId, self.onEvent_setCurPetId)
  L_PetStore:unListenCallFunc(L_PetStore.event.removePet, self.onEvent_removePet)
  L_PetStore:unListenCallFunc(L_PetStore.event.setSelectReleasePet, self.onEvent_setSelectReleasePet)
  L_PetReleaseManager:setIsReleaseMode(false)
  this.super.close(self, options)
  L_PetStore:call(L_PetStore.event.closePetBox)
  L_PetStore:setCurSelectPetId(0)
end

function this:initModule()
  self:initDropDown()
  self:initBoxList()
  self:initPointList()
  self.petGuid = L_PetStore:getCurSelectPetId()
  self:refreshPetProperty(self.petGuid)
end

function this:initDropDown()
  local tmp = {}
  for index, type in ipairs(self.filterType) do
    table.insert(tmp, {
      index = index,
      type = L_WordsTpl:getValue(type),
      txt_name = L_WordsTpl:getValue(type),
      go_icon = false
    })
  end
  self.bind.txt_dropDown = tmp[self.filter].txt_name
  self.bind.list_dropdown:clear()
  self.bind.list_dropdown:insert_array(tmp)
end

function this:initBoxList()
  local tmp = {}
  local petBoxList = L_PetStore:getPetBoxList()
  local petBoxNameList = L_PetStore:getPetBoxNameList()
  for i, v in ipairs(petBoxList) do
    table.insert(tmp, {
      petList = v,
      boxIndex = i,
      boxName = petBoxNameList[i]
    })
  end
  self.bind.loopListBox:clear()
  self.bind.loopListBox:insert_array(tmp)
end

function this:onScrollBox()
  local loopListViewRoot = self.bindComponents.list_petBox
  if loopListViewRoot == nil then
    return
  end
  local index = loopListViewRoot.CurSnapNearestItemIndex
  if index == nil then
    return
  end
  self.realIndex = index
  local snapIndex = index + 1
  local index = self:realSnapToItemIndex(snapIndex)
  self:setPointListActive(index)
end

function this:realSnapToItemIndex(snapIndex)
  local index = snapIndex
  if index == 0 then
    index = #self.bind.loopListBox
  else
    index = index % #self.bind.loopListBox
    index = index == 0 and #self.bind.loopListBox or index
  end
  return index
end

function this:onEvent_setCurPetId(guid)
  self.petGuid = guid
end

function this:onEvent_setSelectReleasePet(guid)
  if guid ~= nil then
    self.petGuid = guid
    self:refreshPetProperty(guid)
  end
end

function this:refreshPetProperty(guid)
  if math.isEmpty(guid) then
    self.bind.show_petBoxProperty = false
    self.bind.show_empty = true
  else
    self.bind.show_petBoxProperty = true
    self.bind.show_empty = false
  end
  local modulePetBoxProperty = self.modules.modulePetBoxProperty
  modulePetBoxProperty:refreshPetProperty(guid)
end

function this:onEvent_removePet(guids)
  L_PetReleaseManager:setIsReleaseMode(false)
  self.modules.moduleCommonTop:setPageName(L_WordsTpl:getValue("notice_pagePetBox_07"))
  if math.isEmpty(self.petGuid) then
    self:refreshPetProperty(self.petGuid)
  else
    for i, v in ipairs(guids) do
      if v == self.petGuid then
        self.petGuid = nil
        local countList = L_PetStore:getPetBoxList(self.data.curIndex)
        for k, id in pairs(countList) do
          if not math.isEmpty(id) then
            self.petGuid = L_PetStore:getPetBoxFirstPet(self.data.curIndex)
            break
          end
        end
        if math.isEmpty(self.petGuid) then
          self:refreshPetProperty(self.petGuid)
        else
          L_PetStore:setCurSelectPetId(self.petGuid)
        end
      end
    end
  end
  self:refreshCurBox()
  self:setReleaseMode()
end

function this:onEvent_changePetBox(box)
  self.bind.moveToItemIndex = box - 1
end

function this:refreshCurBox(isPlaySortAudio)
  self.bind.loopListBox:getItemCls(self.data.curIndex):refresh()
  if isPlaySortAudio then
    L_AudioUtil.playSound("Play_SFX_System_UI_QiboHouse_Sort")
  end
end

function this:refreshAllBox()
  for i = 1, #self.bind.loopListBox do
    self.bind.loopListBox:getItemCls(i):refresh()
  end
end

function this:getFilterType()
  if math.isEmpty(self.filter) then
    self.filter = 1
  end
  return self.filter
end

function this:refreshFilterActive()
  for i = 1, #self.bind.list_dropdown do
    local index = self.bind.list_dropdown:getValue(i, "index")
    if index == self.filter then
      self.bind.list_dropdown:getItemCls(i):setActive(true)
    else
      self.bind.list_dropdown:getItemCls(i):setActive(false)
    end
  end
end

function this:initPointList()
  local tmp = {}
  for i = 1, #self.bind.loopListBox do
    table.insert(tmp, {})
  end
  self.bind.loopListBoxPoint:clear()
  self.bind.loopListBoxPoint:insert_array(tmp)
  self:setPointListActive()
  if self._defaultBoxIndex then
    self.bind.moveToItemIndex = self._defaultBoxIndex - 1
    self._defaultBoxIndex = nil
  elseif math.isEmpty(L_PetStore:getCurSelectPetId()) then
    self.bind.moveToItemIndex = 0
  else
    local index = L_PetStore:getPetItem(L_PetStore:getCurSelectPetId()).box_id // 100
    self.bind.moveToItemIndex = index - 1
  end
end

function this:setPointListActive(itemIndex)
  self.data.curIndex = itemIndex or 1
  local modulePageTabSlider = self.modules.module_pageTabSlider
  modulePageTabSlider:setPageIndex(self.data.curIndex, #self.bind.loopListBox)
  local boxIndexStr = self:indexChange(self.bind.loopListBox[self.data.curIndex].boxIndex)
  local boxName = self.bind.loopListBox[self.data.curIndex].boxName
  self.modules.modulePetRelease:setCurBox(self.data.curIndex, boxIndexStr, boxName)
  self.modules.modulePetRelease:setTabSlider(self.data.curIndex, #self.bind.loopListBox)
  self.bind.curBoxIndex = boxIndexStr
  self.bind.curBoxName = boxName
end

function this:indexChange(index)
  if index < 10 then
    return string.format("0%d", index)
  end
  return tostring(index)
end

function this:check(options, callback)
  local result = L_SystemUnlockManager:checkAndTip(L_SystemConst.enum.pet)
  if not result then
    callback(false)
    return
  end
  if L_FormationStore:getIsTrailFormation(L_FormationManager:getCurFormationType()) then
    L_FlyMsgManager:showNormalMsgByKey("notice_pagePetBox_06")
    callback(false)
    return
  end
  callback(true)
end

function this:configTouch(operator)
  self.onUITouchHandle = self.onUITouchHandle or L_CommonUtil.handle(self.onUI_touchHandle, 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)
  self.onUIClickHandle = self.onUIClickHandle or L_CommonUtil.handle(self.onUI_clickHandle, self)
  C_ScreenTouch.OnUI_LongTapEnd(operator, self.onUIClickHandle)
  C_ScreenTouch.OnUI_Click(operator, self.onUIClickHandle)
  C_ScreenTouch.OnUI_LongTapStart(operator, self.onUITouchHandle)
  C_ScreenTouch.OnUI_Drag(operator, self.onUIDragHandle)
  C_ScreenTouch.OnUI_DragEnd(operator, self.onUIDragEndHandle)
end

function this:getHoldInfo(go)
  for i, module in ipairs(self.modules.loopListBox) do
    if module.bind.boxIndex == self.data.curIndex then
      for n, item in ipairs(module.modules.list_pet) do
        if item:getRaycastGo() == go then
          return item.bind.guid, self.data.curIndex * 100 + n
        end
      end
    end
  end
  return nil, nil
end

function this:setSelectAlpha(boxId, alpha)
  if math.isEmpty(boxId) then
    return
  end
  local index = boxId // 100
  local slot = boxId % 100
  for i, module in ipairs(self.modules.loopListBox) do
    if module.bind.boxIndex == index then
      module.bind.list_pet:getItemCls(slot):setIconAlpha(alpha)
      module.bind.list_pet:change(i, {
        isLongTap = alpha < 1 and true or false
      })
      break
    end
  end
end

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

function this:onUI_touchHandle(gesture)
  if self.bindComponents.rect_drag.gameObject.activeSelf == true then
    return
  end
  if L_PetReleaseManager:getIsReleaseMode() then
    return
  end
  local go = gesture.go
  self.fingerId = gesture.fingerId
  local holdGuid, holdBoxId = self:getHoldInfo(go)
  if math.isEmpty(holdGuid) then
    return
  end
  if not self.isBind then
    return
  end
  local touchPos = L_Vector3.screenToLocalInRectangle(self.bindComponents.rect_content, gesture.position)
  L_AudioUtil.playSound("Play_SFX_System_UI_General_Click_Hold")
  L_FlyMsgManager:startLongPress(gesture, 0.5, function()
    self._holdGuid, self._holdBoxId = holdGuid, holdBoxId
    L_Vector3.setAnchored(self.bindComponents.rect_drag, touchPos)
    self:showDragImg(true, holdGuid, holdBoxId)
  end)
end

function this:onUI_dragHandle(gesture)
  if L_PetReleaseManager:getIsReleaseMode() then
    return
  end
  if self.bindComponents.rect_drag.gameObject.activeSelf == true then
    self.bind.listBoxIsDragging = false
  end
  if gesture.fingerId ~= self.fingerId then
    self.bindComponents.scroll_box.enabled = true
    self.bind.listBoxIsDragging = true
    return
  end
  local touchPos = L_Vector3.screenToLocalInRectangle(self.bindComponents.rect_content, gesture.position)
  L_Vector3.setAnchored(self.bindComponents.rect_drag, touchPos)
end

function this:onUI_dragEndHandle(gesture)
  if L_PetReleaseManager:getIsReleaseMode() then
    return
  end
  if gesture.fingerId ~= self.fingerId then
    return
  end
  local go = gesture:GetCurrentFirstPickedUIElement()
  if not math.isEmpty(self._holdGuid) then
    local holdGuid, holdBoxId = self:getHoldInfo(go)
    if holdGuid == self._holdGuid or holdBoxId == self._holdBoxId then
      self:endDrag()
      return
    end
    if math.isEmpty(holdBoxId) then
      self:endDrag()
      return
    end
    self:handleDragEffect(self._holdGuid, self._holdBoxId, holdGuid, holdBoxId)
  else
    self:endDrag()
  end
end

function this:showDragImg(isShow, holdGuid, holdBoxId)
  if L_PetReleaseManager:getIsReleaseMode() then
    return
  end
  if isShow then
    self:setSelectAlpha(holdBoxId, 0.5)
    local pet = L_PetStore:getPetItem(holdGuid)
    local tpl = _petTpl:getTplById(pet.id)
    self.bind.img_drag = _petTpl:getPetPixelIcon(tpl, pet:isSpecialPet())
    self.bindComponents.scroll_box.enabled = false
    self.bindComponents.rect_drag.gameObject:ActiveTrans(true)
    self.bind.edgeLeft_enable = true
    self.bind.edgeRight_enable = true
    L_AudioUtil.playSound("Play_SFX_System_UI_QiboHouse_PickUp")
    for i, module in ipairs(self.modules.loopListBox) do
      module:setIsDragging(true)
    end
  else
    self:endDrag()
  end
end

function this:handleDragEffect(fromGuid, fromBoxId, toGuid, toBoxId)
  if math.isEmpty(toBoxId) then
    self:endDrag()
    L_AudioUtil.playSound("Play_SFX_System_UI_QiboHouse_Drop")
    return
  end
  if math.isEmpty(toGuid) then
    L_PetStore:req_CSSetPetBox(fromGuid, toBoxId, function()
      self:endDrag()
      L_AudioUtil.playSound("Play_SFX_System_UI_QiboHouse_Drop")
      L_PetStore:setCurSelectPetId(fromGuid)
    end)
  else
    L_PetStore:req_CSExchangePetBoxId(fromGuid, toGuid, function()
      self:endDrag()
      L_AudioUtil.playSound("Play_SFX_System_UI_QiboHouse_Drop")
      L_PetStore:setCurSelectPetId(fromGuid)
    end)
  end
end

function this:endDrag()
  if L_PetReleaseManager:getIsReleaseMode() then
    return
  end
  if not math.isEmpty(self._holdBoxId) then
    self:setSelectAlpha(self._holdBoxId, 1)
  end
  self._holdGuid, self._holdBoxId, self.fingerId = nil, nil, nil
  self.bindComponents.rect_drag.gameObject:ActiveTrans(false)
  self.bindComponents.scroll_box.enabled = true
  self.bind.edgeLeft_enable = false
  self.bind.edgeRight_enable = false
  self.bind.listBoxIsDragging = false
  for i, module in ipairs(self.modules.loopListBox) do
    module:setIsDragging(false)
  end
  self:killAutoDragTimer()
end

function this:createAutoDragTimer(index)
  self:killAutoDragTimer()
  local value = index == 1 and 1 or -1
  self.autoDragTimer = Timer.repeated(1.1, function()
    self.bind.snapToItemIndex = self.realIndex + value
    L_AudioUtil.playSound("Play_SFX_System_UI_QiboHouse_Switch")
  end, self)
end

function this:killAutoDragTimer()
  if self.autoDragTimer then
    Timer.remove(self.autoDragTimer)
    self.autoDragTimer = nil
  end
end

function this:initSystem()
  self.systemToTrans = {
    [L_SystemConst.enum.petRelease] = {
      self.bindComponents.btnPetFreeTrans
    }
  }
  for systemId, v in pairs(self.systemToTrans) do
    v.locker = L_SystemUnlockManager:tryGenerateLocker(systemId)
    if v.locker then
      self:refreshSystem(systemId, false)
      v.locker:setCallback(self.refreshSystem, self, self.gameObject)
    end
  end
end

function this:refreshSystem(systemId, isUnlock)
  local node = self.systemToTrans[systemId]
  local locker = node.locker
  for _, v in ipairs(node) do
    locker:tryShowOrHide(v, isUnlock)
  end
end

function this:setReleaseMode()
  local isFreeMode = L_PetReleaseManager:getIsReleaseMode()
  self.bind.btnPetFreeActive = not isFreeMode
  self.bind.modulePetReleaseActive = isFreeMode
  self.bind.boxInfoActive = not isFreeMode
  self.bind.downBgActive = not isFreeMode
  self.modules.modulePetBoxProperty:setDetailBtnActive(not isFreeMode)
  if isFreeMode then
    self.bind.boxGroupPos = C_Vector2(-1150, -141)
  else
    self.bind.boxGroupPos = C_Vector2(-1150, -62)
  end
end

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

function this:closePageFunc()
  if L_PetReleaseManager:getIsReleaseMode() then
    L_PetReleaseManager:setIsReleaseMode(false)
    self:setReleaseMode()
    L_PetStore:setCurSelectPetId(L_PetStore:getPetBoxFirstPet(self.data.curIndex))
    self.modules.moduleCommonTop:setPageName(L_WordsTpl:getValue("notice_pagePetBox_07"))
  else
    L_UI:close(self.pageName)
  end
end

return this
