local this = {}
local guideConditionTpl = L_GameTpl:getGuideConditionTpl()
local guideGroupTpl = L_GameTpl:getGuideGroupTpl()
local guideConditionTypeTpl = L_GameTpl:getGuideConditionTypeTpl()

function this:parseGuideParams(params)
  if not L_PlayerStore:isPlayerLogin() then
    return
  end
  if L_LoadingManager:isLoading() then
    return
  end
  local triggerConditions = {}
  local guideParams = params.guideParams
  guideParams = guideParams or {}
  for _, param in ipairs(guideParams) do
    if param.type then
      local conditions = guideConditionTpl:getConditionsByType(param.type)
      if not conditions then
        printf("guide parser", "guideCondition\232\161\168\230\178\161\230\156\137condition\231\177\187\229\158\139\239\188\154 " .. param.type)
        return
      end
      for _, condition in ipairs(conditions) do
        local conditionValue = self:convertType(guideConditionTpl:getParam(condition), guideConditionTpl:getParamType(condition))
        local paramValue = self:convertType(param.param, guideConditionTpl:getParamType(condition))
        local funcName = string.concat("parse", param.type)
        if self[funcName] then
          if self[funcName](conditionValue) then
            table.insert(triggerConditions, guideConditionTpl:getId(condition))
          end
        elseif conditionValue == paramValue or self:checkIsSpecialCondition(param.type, conditionValue) then
          table.insert(triggerConditions, guideConditionTpl:getId(condition))
        end
      end
    end
  end
  return self:checkAllGudieGroup(triggerConditions, params.callBack)
end

function this:checkAllGudieGroup(triggerConditions, callback)
  local triggerGroupIds = {}
  local guideGroups = guideGroupTpl:getData()
  local addCallback = false
  for _, group in pairs(guideGroups) do
    local guideId = guideGroupTpl:getId(group)
    addCallback = false
    if guideGroupTpl:getIsWorking(group) and not L_GuideStore:isGuideComplete(guideId) and (#guideGroupTpl:getGuideAndCondition(group) > 0 or 0 < #guideGroupTpl:getGuideOrCondition(group)) then
      local andRes, addAndCallback = self:getAndConditionResult(group, triggerConditions)
      local orRes, andOrCallback = self:getOrConditionResult(group, triggerConditions)
      if andRes and orRes then
        if addAndCallback or andOrCallback then
          self._guideFinishedCallback[guideId] = callback
        end
        table.insert(triggerGroupIds, guideGroupTpl:getId(group))
      end
    end
  end
  table.sort(triggerGroupIds)
  return triggerGroupIds
end

function this:getAndConditionResult(tpl, triggerConditions)
  local conditions = guideGroupTpl:getGuideAndCondition(tpl)
  if #conditions == 0 then
    return true, false
  end
  local conditionRes, addCallback = self:checkConditions(conditions, triggerConditions)
  local res = not table.containsValue(conditionRes, false)
  return res, addCallback
end

function this:getOrConditionResult(tpl, triggerConditions)
  local conditions = guideGroupTpl:getGuideOrCondition(tpl)
  if #conditions == 0 then
    return true, false
  end
  local conditionRes, addCallback = self:checkConditions(conditions, triggerConditions)
  local res = table.containsValue(conditionRes, true)
  return res, addCallback
end

function this:checkConditions(conditions, triggerConditions)
  local conditionRes = {}
  local addCallback = false
  for _, condition in ipairs(conditions) do
    if table.containsValue(triggerConditions, condition) then
      table.insert(conditionRes, true)
      addCallback = true
    else
      local conditionTpl = guideConditionTpl:getTplById(condition)
      if conditionTpl == nil then
        printf("guide parser", "guideCondition\232\161\168\230\178\161\230\156\137id\239\188\154 " .. condition)
      else
        local conditionValue = self:convertType(guideConditionTpl:getParam(conditionTpl), guideConditionTpl:getParamType(conditionTpl))
        local cType = guideConditionTpl:getType(conditionTpl)
        local funcName = string.concat("parse", cType)
        if self:checkIsSpecialConditionForMoment(cType, conditionValue) then
          table.insert(conditionRes, true)
        elseif self[funcName] then
          table.insert(conditionRes, self[funcName](conditionValue))
        else
          table.insert(conditionRes, false)
        end
      end
    end
  end
  return conditionRes, addCallback
end

function this:convertType(value, targetType)
  if value == nil then
    return 0
  end
  if targetType == "string" then
    return tostring(value)
  elseif targetType == "int" then
    local converted = tonumber(value)
    if converted == nil then
      return 0
    end
    return converted
  elseif targetType == "list<int>" then
    local splitList = string.split(value, "|")
    local converted = {}
    for _, v in ipairs(splitList) do
      if not string.isEmpty(v) then
        table.insert(converted, tonumber(v))
      end
    end
    return converted
  else
    errorf("Unsupported target type: " .. tostring(targetType), 2)
  end
end

function this.parse1001(param)
  return L_TaskStore:checkTaskIsFinished(param)
end

function this.parse1004(param)
  return C_TaskManager.CheckTaskNodeIsFinished(param[1], param[2])
end

function this.parse3001(param)
  if not L_PlayerStore:isPlayerLogin() then
    return false
  end
  return L_SystemUnlockStore:getSystemIsOpen(param)
end

function this.parse3002(param)
  return L_UI:checkPageOpen(param)
end

function this.parse3004(param)
  local playerLevel = L_PlayerStore:getLv()
  return param <= playerLevel
end

function this.parse3005(param)
  if not L_CommonUtil.isValid(AzurWorldInstance) or AzurWorld.proxyCenter == nil then
    return false
  end
  local currentSceneId = AzurWorldInstance.CurWorldId
  if currentSceneId == nil then
    return false
  end
  return table.containsValue(param, currentSceneId)
end

function this.parse3006(param)
  local isHome = L_HomeUtil.isInHome() and 1 or 0
  if L_WorldManager:getCurModule() == nil then
    return false
  end
  return param == isHome
end

function this.parse3008(param)
  return L_GuideStore:isGuideComplete(param)
end

function this.parse3007(param)
  if param == 0 then
    return true
  end
  return 0 < L_TechnologyStore:getCurTechnologyLevelById(param)
end

function this.parse3009(param)
  local vaildHeros = L_FormationStore:getCurTeamValidHeroes(L_FormationConst.FormationType.world)
  return table.count(vaildHeros) == param
end

function this:checkIsSpecialCondition(type, value)
  if type == L_Const.specialGuideCondition.range then
    if math.isEmpty(value) then
      return self.isCloseToSpecial
    end
    return false
  end
  return math.isEmpty(value)
end

function this:checkIsSpecialConditionForMoment(type, value)
  local tpl = guideConditionTypeTpl:getTplById(type)
  if guideConditionTypeTpl:getIsMoment(tpl) then
    return false
  end
  if type == L_Const.specialGuideCondition.range then
    if math.isEmpty(value) then
      return self.isCloseToSpecial
    end
    return false
  end
  return math.isEmpty(value)
end

return this
