local this = L_BevTree:registClass("guide.describeAction", L_BevTree.action)
local guideStuckTime = L_Config:getConfig("game", "GUIDE_SKIP_BUTTON_DISPLAY_TIME")

function this:param()
  self.pageName = ""
  self.targetPath = ""
  self.effectPath = ""
  self.dimension = ""
  self.effectScale = ""
  self.offset = ""
  self.delayPlayTime = 0
  self.headIcon = ""
  self.arrowDirection = 5
  self.wordsIds = ""
  self.storyTextIds = ""
  self.tipPos = ""
  self.isUseMask = 0
  self.isListItem = 0
  self.inputActions = ""
  self.validPages = ""
end

function this:parse()
  self.pageName = self:getParam("pageName")
  self.targetPath = self:getParam("targetPath")
  self.effectPath = self:getParam("effectPath")
  self.effectScale = self:getParam("effectScale")
  self.offset = self:getParam("offset")
  self.isListItem = self:getParam("isListItem", true)
  self.dimension = self:getParam("dimension")
  self.isUseListItem = self:getParam("isListItem", true) ~= 0
  self.delayPlayTime = self:getParam("delayPlayTime", true) or 0
  self.isUseMask = self:getParam("isUseMask", true) ~= 0
  self.tipPos = self:getParam("tipPos")
  self.delayTime = self:getParam("delayTime", true) or 0
  self.inputActions = self:getParam("inputActions")
  self.storyTextIds = self:getParam("storyTextIds")
  self.wordsIds = self:getParam("wordsIds")
  self.headIcon = self:getParam("headIcon")
  self.isDestroy = false
  self.validPages = self:getParam("validPages") or ""
  self.arrowDirection = self:getParam("arrowDirection", true) or 5
  self.validPages = string.split(self.validPages, "|")
  table.insert(self.validPages, self.pageName)
end

function this:onEnter()
  if self.isDestroy then
    self.result = L_BevTree.taskResult.Failure
    return
  end
  self.lastStuck = false
  self.result = L_BevTree.taskResult.Running
  self:blockAllAction()
  self.curCheckTime = C_Time.time
  L_GuideManager:internalSendEvent(G_GuideClasses.GuideEvent.ShowSkipGuide, {
    guideId = self.tree.param.guideId,
    isShow = false
  })
end

function this:checkUIShow()
  local isShow = L_GuideManager:checkCurrentAllPages(self.validPages)
  if L_CommonUtil.isValid(self.effectGameObject) then
    self.validPages = self.validPages or {}
    if self.lastIsShow ~= isShow then
      self.effectGameObject:SetActive(isShow)
    end
    self.lastIsShow = isShow
  end
  local isStuck = self.isUseMask and C_Time.time - self.curCheckTime >= guideStuckTime
  if isStuck ~= self.lastStuck then
    L_GuideManager:internalSendEvent(G_GuideClasses.GuideEvent.ShowSkipGuide, {
      skipNotSave = self.skipNotSave,
      guideId = self.tree.param.guideId,
      isShow = isStuck
    })
    if not isStuck then
      self:dealHighInputAction()
    end
  end
  self.lastStuck = isStuck
  if not isShow then
    return
  end
  self:checkClickStuck()
end

function this:checkClickStuck()
  if not L_GuideManager:checkPageOpen(self.pageName) then
    return
  end
  local page = L_UI:getPage(self.pageName)
  if page == nil or page.gameObject == nil then
    return
  end
  local parent = self:getParentTrans(page)
  if parent == nil then
    return
  end
  if not parent.gameObject.activeInHierarchy or not parent.gameObject.activeSelf then
    return
  end
  self.curCheckTime = C_Time.time
end

function this:execute()
  if string.isEmpty(self.effectPath) then
    printf("guide\230\143\144\231\164\186", "\231\137\185\230\149\136\232\183\175\229\190\132\230\152\175\231\169\186\231\154\132describeAction\229\191\133\233\161\187\233\133\141\229\144\136\231\137\185\230\149\136\228\189\191\231\148\168  ID: " .. self.id)
    self.result = L_BevTree.taskResult.Failure
  end
  if self.result == L_BevTree.taskResult.Success or self.result == L_BevTree.taskResult.Failure then
    return self.result
  end
  if self.result == L_BevTree.taskResult.Running then
    self:checkUIShow()
  end
  if self.waitClick then
    if not L_CommonUtil.isValid(self.effectGameObject) and not self.waitDelay then
      self:dealClickFinished(true)
    end
    return self.result
  end
  local parentTrans
  local page = L_UI:getPage(self.pageName)
  if L_GuideManager:checkPageOpen(self.pageName) then
    parentTrans = self:getParentTrans(page)
  else
    L_UI:setTempTopGuideMask(false)
    return L_BevTree.taskResult.Running
  end
  if L_UI:checkPagePlayingAnim(page) then
    if not self.isPlayingAnimation then
      L_UI:setTempTopGuideMask(true)
    end
    self.isPlayingAnimation = true
    self.result = L_BevTree.taskResult.Running
    return L_BevTree.taskResult.Running
  end
  if not L_CommonUtil.isValid(parentTrans) then
    self.result = L_BevTree.taskResult.Running
    L_UI:setTempTopGuideMask(false)
    return L_BevTree.taskResult.Running
  end
  if not parentTrans.gameObject.activeInHierarchy or not parentTrans.gameObject.activeSelf then
    self.result = L_BevTree.taskResult.Running
    L_UI:setTempTopGuideMask(false)
    return L_BevTree.taskResult.Running
  end
  self.waitClick = true
  self.waitDelay = true
  L_UI:setTempTopGuideMask(true)
  Timer.once(self.delayPlayTime, function()
    L_UI:setTempTopGuideMask(false)
    if self.delayPlayTime ~= nil and self.delayPlayTime > 0 and not self:dealHighInputAction() then
      C_InputManager.DisableHighLevelControl()
    end
    if self.result == L_BevTree.taskResult.Failure then
      return self.result
    end
    self:dealEffect(parentTrans)
    self:dealShowGuideClickTips(parentTrans, self.effectGameObject)
    self:dealHighInputAction()
    self.waitDelay = false
    self.isPlayingAnimation = false
  end, self)
  return self.result
end

function this:dealShowGuideClickTips(parentTrans, effectGameObject)
  L_GuideManager:internalSendEvent(G_GuideClasses.GuideEvent.GuideControlMouse, {key = "guideClick", isShow = true})
  if not L_CommonUtil.isValid(parentTrans) then
    return
  end
  if self.isDestroy then
    return
  end
  self.finishCallback = self.finishCallback or handler(self, self.dealClickFinished)
  self.showTipData = {
    parentTrans = parentTrans,
    effectGameobject = effectGameObject,
    isDescribeAction = true,
    tipPos = self.tipPos,
    validPages = self.validPages,
    headIcon = self.headIcon,
    storyTextIds = self.storyTextIds,
    wordsIds = self.wordsIds,
    finishCallback = self.finishCallback,
    arrowDirection = self.arrowDirection
  }
  L_UI:open("pageGuideClickTips", self.showTipData)
end

function this:disposeTimer()
  if self.showTimer ~= nil then
    Timer.remove(self.showTimer)
    self.showTimer = nil
  end
end

function this:dealEffect(parentTrans)
  if self.result == L_BevTree.taskResult.Failure then
    return
  end
  if self.isDestroy then
    return
  end
  local page = L_UI:getPage(self.pageName)
  if page == nil then
    self.result = L_BevTree.taskResult.Failure
    return
  end
  local scale, dimension
  local offset = C_Vector2.zero
  if not self.isDestroy then
    if not string.isEmpty(self.effectScale) then
      local scaleSplit = string.split(self.effectScale, "|")
      scale = L_Vector3.new(tonumber(scaleSplit[1]), tonumber(scaleSplit[2]), 1)
    end
    if not string.isEmpty(self.dimension) then
      local dimensionSplit = string.split(self.dimension, "|")
      dimension = C_Vector2(tonumber(dimensionSplit[1]), tonumber(dimensionSplit[2]))
    end
    if not string.isEmpty(self.offset) then
      local offsetSplit = string.split(self.offset, "|")
      offset = C_Vector2(tonumber(offsetSplit[1]), tonumber(offsetSplit[2]))
    end
  end
  local board = page.gameObject.transform:Find("board") or page.gameObject.transform:Find("Board")
  board = board or page.gameObject.transform
  local parentRect = parentTrans:GetComponent(typeof(C_RectTransform))
  local targetWorldPosition = parentRect:TransformPoint(C_Vector3.zero)
  self.effectGameObject = L_EffectUtil.playEffect(self.effectPath, board, scale, offset, dimension, targetWorldPosition)
  if L_CommonUtil.isValid(self.effectGameObject) and not self.isDestroy then
    local guideFxManager = self.effectGameObject:GetComponentInChildren(typeof(CS.Lens.Framework.UI.LGuideFxManager))
    if guideFxManager then
      guideFxManager.useMask = self.isUseMask
      guideFxManager.useEventTransfer = false
      guideFxManager:InitGuide()
    end
  end
end

function this:dealClickFinished(isDestroy)
  if self.isClickBlock then
    return
  end
  if isDestroy then
    self.result = L_BevTree.taskResult.Failure
  else
    self.result = L_BevTree.taskResult.Success
  end
  if L_UI:checkPageOpen("pageGuideClickTips") then
    L_UI:close("pageGuideClickTips")
  end
end

function this:onReset()
  self.isDestroy = true
  self.result = L_BevTree.taskResult.Failure
  self:dealDestroy()
  self:disposeTimer()
end

function this:onDestroy()
  self:doDestroy()
end

function this:doDestroy()
  self:dealDestroy()
  L_GuideManager:internalSendEvent(G_GuideClasses.GuideEvent.ShowSkipGuide, {
    guideId = self.tree.param.guideId,
    isShow = false
  })
  L_GuideManager:internalSendEvent(G_GuideClasses.GuideEvent.GuideControlMouse, {key = "guideClick", isShow = false})
end

function this:onFinish()
  self.isDestroy = true
  self:doDestroy()
end

function this:dealDestroy()
  if L_CommonUtil.isValid(self.effectGameObject) and self.isDestroy then
    C_GameObject.DestroyImmediate(self.effectGameObject.gameObject)
  end
  if L_UI:checkPageOpen("pageGuideClickTips") then
    L_UI:close("pageGuideClickTips")
  end
  L_UI:setTempTopGuideMask(false)
  self:dealDisableHighInputAction()
end

function this:blockAllAction()
  if self.isUseMask then
    C_InputManager.EnableHighLevelControl({}, nil)
  end
end

function this:dealHighInputAction()
  if not string.isEmpty(self.inputActions) then
    local actions = string.split(self.inputActions, "|")
    C_InputManager.EnableHighLevelControl(actions, nil)
    return true
  end
  if string.isEmpty(self.inputActions) then
    C_InputManager.DisableHighLevelControl()
  end
  return false
end

function this:dealDisableHighInputAction()
  if not string.isEmpty(self.inputActions) then
    C_InputManager.DisableHighLevelControl()
  end
end

function this:getParentTrans(page)
  local parentTrans
  if self.isUseListItem then
    parentTrans = self.tree.targetListItem.transform
  elseif string.isEmpty(self.targetPath) then
    parentTrans = page.transform
  else
    parentTrans = page.gameObject.transform:Find(self.targetPath)
  end
  return parentTrans
end

return this
