local this = L_BevTree:registClass("guide.guideClick", 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.headDirection = 0
  self.tipsKey = ""
  self.storyTextId = ""
  self.arrowDirection = 0
  self.arrowPos = ""
  self.tipPos = ""
  self.tipOffset = ""
  self.showTime = 0
  self.showKeys = ""
  self.longPressKeys = ""
  self.longPressTime = 0
  self.isHideMask = 0
  self.isListItem = 0
  self.isClickBlock = 0
  self.skipNotSave = 0
  self.useEventTransfer = 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.isUseEventTransfer = self:getParam("useEventTransfer", true) == 0
  self.delayPlayTime = self:getParam("delayPlayTime", true) or 0
  self.isHideMask = self:getParam("isHideMask", true) ~= 0
  self.arrowDirection = self:getParam("arrowDirection", true) or 4
  self.arrowPos = self:getParam("arrowPos")
  self.tipPos = self:getParam("tipPos")
  self.tipsKey = self:getParam("tipsKey")
  self.showKeys = self:getParam("showKeys")
  self.showTime = self:getParam("showTime", true) or 0
  self.longPressKeys = self:getParam("longPressKeys")
  self.longPressTime = self:getParam("longPressTime", true) or 0
  self.delayTime = self:getParam("delayTime", true) or 0
  self.inputActions = self:getParam("inputActions")
  self.isClickBlock = self:getParam("isClickBlock", true)
  self.isClickBlock = self.isClickBlock ~= 0 and self.isClickBlock ~= nil
  self.isDestroy = false
  self.validPages = self:getParam("validPages") or ""
  self.skipNotSave = self:getParam("skipNotSave", true) or 0
  self.tipOffset = self:getParam("tipOffset")
  self.headDirection = self:getParam("headDirection", true) or 0
  self.storyTextId = self:getParam("storyTextId")
  self.headIcon = self:getParam("headIcon")
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:dealDetectKeys()
  self.curCheckTime = C_Time.time
  L_GuideManager:internalSendEvent(G_GuideClasses.GuideEvent.ShowSkipGuide, {
    guideId = self.tree.param.guideId,
    isShow = false
  })
end

function this:dealDetectKeys()
  local tips = L_WordsTpl:getValue(self.tipsKey)
  self.isDetectLongPress = not string.isEmpty(self.longPressKeys) and self.longPressTime > 0
  self.isDetectKeys = not string.isEmpty(self.showKeys)
  local showKeys = {}
  if self.isDetectKeys then
    showKeys, self.pressKeys, self.comboKeys = L_GuideManager:getCheckKeys(self.showKeys)
  end
  if self.isDetectLongPress then
    self.longPressKey = Unity.KeyCode[self.longPressKeys]
    self.isPressed = false
  end
  self.validPages = string.split(self.validPages, "|")
  table.insert(self.validPages, self.pageName)
  self.showTipData = {
    showTips = tips,
    showKeys = showKeys,
    longPressKey = self.longPressKeys,
    showTime = self.showTime,
    tipPos = self.tipPos,
    arrowDirection = self.arrowDirection,
    arrowPos = self.arrowPos,
    showPageName = self.pageName,
    validPages = self.validPages,
    tipOffset = self.tipOffset,
    headDirection = self.headDirection,
    storyTextId = self.storyTextId,
    headIcon = self.headIcon
  }
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 = not self.isHideMask 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\132forceClick\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
  self:checkWaitResult()
  if self.result == L_BevTree.taskResult.Success or self.result == L_BevTree.taskResult.Failure then
    return self.result
  end
  if self.waitSuccess or self.waitFailure 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
    if self.startCheckInput then
      self:dealDetectInputAction()
    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_GuideManager:isPlayingEnterAnimation(page) then
    if not self.isPlayingAnimation and not self.isDestroy 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)
  if self.delayPlayTime ~= nil and self.delayPlayTime > 0 then
    C_InputManager.EnableHighLevelControl({}, nil)
  end
  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:dealHighInputAction()
    self.waitDelay = false
    self.isPlayingAnimation = false
    self.startCheckInput = true
  end, self)
  return self.result
end

function this:dealShowGuideClickTips(parentTrans, effectGameObject, dimension)
  if not self.showTipData or string.isEmpty(self.showTipData.showTips) and string.isEmpty(self.showTipData.storyTextId) then
    return
  end
  if not L_CommonUtil.isValid(parentTrans) then
    return
  end
  self.showTipData.parentTrans = parentTrans
  self.showTipData.effectGameobject = effectGameObject
  self.showTipData.effectSize = dimension
  L_UI:open("pageGuideClickTips", self.showTipData)
end

function this:dealDetectInputAction()
  if self.result == L_BevTree.taskResult.Success or self.result == L_BevTree.taskResult.Failure then
    return
  end
  if not self.waitClick then
    return
  end
  if not self.waitAction and self.showTime ~= nil and self.showTime > 0 then
    self.waitAction = true
    self:disposeTimer()
    self.showTimer = Timer.once(self.showTime, function()
      self.waitAction = false
      if self.isHideMask then
        self.waitFailure = true
      else
        self.waitSuccess = true
      end
    end)
  end
  local keyCorrect = false
  if self.isDetectKeys then
    keyCorrect = L_GuideManager:checkInputAction(self.pressKeys, self.comboKeys)
  end
  if not keyCorrect and self.isDetectLongPress then
    keyCorrect = self:checkLongPressAction()
  end
  if keyCorrect then
    self.waitSuccess = true
    self.bSendEvent = true
    L_GuideManager:internalSendEvent(G_GuideClasses.GuideEvent.GuideClickInputChecked)
  end
end

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

function this:checkLongPressAction()
  local keyCorrect = false
  if self.longPressKey ~= nil then
    if Unity.Input.GetKeyDown(self.longPressKey) then
      self.isPressed = true
      self.curTime = C_Time.time
    elseif Unity.Input.GetKey(self.longPressKey) and self.isPressed and self.curTime ~= nil then
      if C_Time.time - self.curTime >= self.longPressTime then
        keyCorrect = true
      end
    elseif Unity.Input.GetKeyUp(self.longPressKey) then
      self.isPressed = false
      self.curTime = nil
    end
  end
  return keyCorrect
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 offsetFromPivot = C_Vector3((0.5 - parentRect.pivot.x) * parentRect.rect.width, (0.5 - parentRect.pivot.y) * parentRect.rect.height, 0)
  local targetWorldPosition = parentRect:TransformPoint(offsetFromPivot)
  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
      self.scrollRect = parentTrans.gameObject:GetComponentInParent(typeof(C_LScrollRect))
      self.scrollView = parentTrans.gameObject:GetComponentInParent(typeof(CS.UnityEngine.UI.ScrollRect))
      self:setScrollDisable(true)
      self:changeLongPressStatus(false)
      guideFxManager.useMask = not self.isHideMask
      guideFxManager.useEventTransfer = self.isUseEventTransfer
      if self.isClickBlock then
        guideFxManager:InitGuide()
      else
        guideFxManager:InitGuide(parentTrans.gameObject)
      end
      self.finishCallback = self.finishCallback or handler(self, self.dealClickFinished)
      guideFxManager:RemoveClickCheckHandler(self.finishCallback)
      guideFxManager:AddClickCheckHandler(self.finishCallback)
    end
  end
  if not self.isHideMask and not self.isDestroy then
    L_GuideManager:internalSendEvent(G_GuideClasses.GuideEvent.GuideControlMouse, {key = "guideClick", isShow = true})
  end
  self:dealShowGuideClickTips(parentTrans, self.effectGameObject, dimension)
end

function this:changeLongPressStatus(status)
  C_LButton.GlobalLongInteractable = status
end

function this:setScrollDisable(disable)
  if L_CommonUtil.isValid(self.scrollRect) then
    self.scrollRect.disableScroll = disable
  end
  if L_CommonUtil.isValid(self.scrollView) then
    self.scrollView.enabled = not disable
  end
end

function this:dealClickFinished(isDestroy)
  if self.isClickBlock then
    return
  end
  if isDestroy then
    self.result = L_BevTree.taskResult.Failure
    if L_UI:checkPageOpen("pageGuideClickTips") then
      L_UI:close("pageGuideClickTips")
    end
  else
    self.waitSuccess = true
    L_GuideManager:internalSendEvent(G_GuideClasses.GuideEvent.GuideClickPass)
  end
end

function this:checkWaitResult()
  if not self.waitSuccess and not self.waitFailure then
    return
  end
  if not L_UI:checkPageOpen("pageGuideClickTips") then
    if self.waitSuccess then
      self.result = L_BevTree.taskResult.Success
    end
    if self.waitFailure then
      self.result = L_BevTree.taskResult.Failure
    end
  end
end

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

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

function this:doDestroy()
  self:dealDestroy()
  L_GuideManager:internalSendEvent(G_GuideClasses.GuideEvent.ShowSkipGuide, {
    guideId = self.tree.param.guideId,
    isShow = false
  })
  if not self.isHideMask then
    L_GuideManager:internalSendEvent(G_GuideClasses.GuideEvent.GuideControlMouse, {key = "guideClick", isShow = false})
  end
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 not self.bSendEvent and L_UI:checkPageOpen("pageGuideClickTips") then
    L_UI:close("pageGuideClickTips")
  end
  self.bSendEvent = false
  self:setScrollDisable(false)
  self:changeLongPressStatus(true)
  L_UI:setTempTopGuideMask(false)
  self:dealDisableHighInputAction()
end

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

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

function this:dealDisableHighInputAction()
  if not self.isHideMask and 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
