---------------------------------------------------------------
-- 指引

-- db.guide.id              指引id
-- db.guide.step            步骤
-- db.guide.state           状态
-- db.guide.cmd2id          cmd->id
-- db.guide.flags           特殊指引标记，是否完成
---------------------------------------------------------------

local Config = require("Config")
Json = Json or require("common.Json")
local GuideExcel = require("excel.guide")
local Util = require("common.Util")
local Log = require("common.Log")
local Msg = require("core.Msg")
local ObjHuman = require("core.ObjHuman")
local Grid = require("bag.Grid")
local BagLogic = require("bag.BagLogic")
local ItemDefine = require("bag.ItemDefine")
local BattleLogic = require("battle.BattleLogic")
local LoginSignLogic = require("loginSign.LoginSignLogic")
local PanelDefine = require("broadcast.PanelDefine")
local SceneHandler = require("scene.Handler")
local RoleExcel = require("excel.role")
local CombatLogic = require("combat.CombatLogic")
local HeroGrid = require("hero.HeroGrid")
local HeroLogic = require("hero.HeroLogic")
local CombatDefine = require("combat.CombatDefine")
local CombatPosLogic = require("combat.CombatPosLogic")
local RoleDefine = require("role.RoleDefine")
local CombatExcel = require("excel.combat")
local OpenActExcel = require("excel.openAct")
local OpenAct = require("present.OpenAct")
local CommonDB = require("common.CommonDB")
local OpenServerGiftLogic = require("present.OpenServerGiftLogic")
local MaiDianDefine = require("MaiDian.MaiDianDefine")
local MainDianLogic = require("MaiDian.MaiDianLogic")
local GuideJumpExcel = require("excel.guideJump")
local CommonDefine = require("common.CommonDefine")

local WeiLen = 30
local GUIDECMD_LIST = {"battle"}
local GUIDEID_FIRST = 0
local GUIDEID_SPECIALSID = 103

local FORCE_GUIDE_CHANNEL_LIST = { --即使问卷调查选对游戏, 依然要强制新手引导的渠道
    [CommonDefine.CHANNEL_TAG_MINNIGAME] = true,
}


-- 指引中断处理方式
SKIPTYPE_RESET = 0              -- 该指引重新从第一步开始
SKIPTYPE_JUMP = 1               -- 该指引直接跳过
SKIPTYPE_JUMP_NAME = 2          -- 改名跳过该指引
SKIPTYPE_JUMP_DRAW = 3          -- 期间进行过高级抽奖，直接跳过
SKIPTYPE_JUMP_HERO = 4          -- 期间获得过英雄，直接跳过
SKIPTYPE_JUMP_HEROUP = 5        -- 英雄升级指定次数
SKIPTYPE_JUMP_BATTLE_REWARD = 7 -- 战役通关奖励
SKIPTYPE_JUMP_SHOPBUY = 8       -- 商店购买
SKIPTYPE_JUMP_OL_REWARD = 9     -- 在线奖励
SKIPTYPE_JUMP_LOGINSIGN = 10    -- 签到
SKIPTYPE_JUMP_BATTLE_SD = 11    -- 战役扫荡
SKIPTYPE_JUMP_BATTLE = 12       -- 战役
SKIPTYPE_JUMP_BATTLE_EXP = 13   -- 是否领取经验
SKIPTYPE_JUMP_LEVEL_GIFT = 14   -- 领取等级礼包
SKIPTYPE_JUMP_OPEN_SERVER_GIFT = 15   -- 领取开服有礼礼包
SKIPTYPE_JUMP_UPGRADE = 16   -- 英雄指定进阶次数
SKIPTYPE_JUMP_JIBAN_GROUP = 17   -- 添加过羁绊组合
SKIPTYPE_JUMP_JIEFENG_BAOJU = 18   -- 解封过宝具奖励
SKIPTYPE_JUMP_BATTLE_GUAJI = 19   -- 领取过挂机奖励
SKIPTYPE_JUMP_BARTASK = 20      -- 悬赏
SKIPTYPE_JUMP_FINISH = 21      -- 直接全部跳过

-- 状态
STATE_DOING = 1         -- 进行中
STATE_FINISH = 2        -- 完成

GUIDE_COMBAT_INFO = GUIDE_COMBAT_INFO or { db = {} }

-- 开服第8天 除了取名的指引 其余一律跳过
local function initGuideHeroList()
    local combatConf = CombatExcel.gm[888888]
    if not combatConf then return end

    GUIDE_COMBAT_INFO.attacker = {}
    GUIDE_COMBAT_INFO.defender = {}
    GUIDE_COMBAT_INFO.atkFormation = combatConf.atkF
    GUIDE_COMBAT_INFO.defFormation = combatConf.defF

    local atkConf = nil
    for i = 1, CombatDefine.COMBAT_HERO_CNT do
        atkConf = nil
        for k, v in ipairs(combatConf.atk) do
           if i == v[2] then
              atkConf = v
              break
           end
        end
        if atkConf then
           GUIDE_COMBAT_INFO.attacker[i] = CombatLogic.createHeroObj(GUIDE_COMBAT_INFO, atkConf[1], atkConf[3], atkConf[4], i, atkConf[5])
        end 

        atkConf = nil
        for k, v in ipairs(combatConf.def) do
           if i == v[2] then
              atkConf = v
              break
           end
        end
        if atkConf then
           GUIDE_COMBAT_INFO.defender[i] = CombatLogic.createHeroObj(GUIDE_COMBAT_INFO, atkConf[1], atkConf[3], atkConf[4], i, atkConf[5])
        end
    end
    
    GUIDE_COMBAT_INFO.init = 1 
end

function initAfterHot()
    if GUIDE_COMBAT_INFO.combat ~= nil then
       return
    end
    GuideExcel = require("excel.guide")
    -- 初始化剧情动画
    initGuideHeroList()
    if not GUIDE_COMBAT_INFO.init then return end

	CombatLogic.combatGuide(GUIDE_COMBAT_INFO, GUIDE_COMBAT_INFO.atkFormation, GUIDE_COMBAT_INFO.attacker, 
    GUIDE_COMBAT_INFO.defFormation, GUIDE_COMBAT_INFO.defender)
end

local function sendjumpinfo(human)
    local tMsgData = Msg.gc.GC_GUIDE_WENJUAN
    tMsgData.tList[0] = #GuideJumpExcel.Jump

    for nID, v in ipairs(GuideJumpExcel.Jump) do
        local tData = tMsgData.tList[nID]
        tData.nID = nID
        tData.szName = v.szName
    end

    tMsgData.tPrize[0] = #GuideJumpExcel.Prize[1].tPrize

    for index, v in ipairs(GuideJumpExcel.Prize[1].tPrize) do
        Grid.makeItem(tMsgData.tPrize[index], v[1], v[2])
    end

    Msg.send(tMsgData, human.fd)
end

------------------------------ data --------------------------------------

-- 设置指引
function setGuide(human, id, state, skipType)
    local cf = GuideExcel.main_guide[id]
    if not cf then return end

    human.db.guide = human.db.guide or {}
    local oldstate = human.db.guide.state
    local oldid = human.db.guide.id 
    if (oldid == id) and (oldstate == state) then
        return -- 老的和新的一致
    end

    local guide = human.db.guide
    local oldcmdid = getGuideIDByCmd(human, cf.cmd)
    guide.id = id 
    guide.state = state
    guide.step = 0
    guide.cmd2id = guide.cmd2id or {}
    guide.cmd2id[cf.cmd] = id
    guide.flags = nil

    if state == STATE_DOING then
        if oldcmdid < id then
            -- 触发指引给东西      
            BagLogic.addItemList(human, cf.items, "guide")
        end
    end
    
    if state == STATE_FINISH then
        -- Log.write(Log.LOGID_OSS_GUIDE_MAIN, human.db._id, human.db.account, human.db.name, human.db.lv, human.db.ip, 
        --     human.pf or "", human.appid, id, skipType or 0)
        Log.write(Log.LOGID_OSS_GUIDE_MAIN, human.db._id, human.db.newUniqueTag, human.db.name, human.db.lv, human.db.ip, 
        human.pf or "", human.appid, id, skipType or 0)
    end
end

-- 获取id
function getGuideID(human)
    if not human.db.guide then 
        return 
    end
    return human.db.guide.id
end

-- 
function getGuideState(human)
    if not human.db.guide then 
        return 
    end
    return human.db.guide.state 
end

function getGuideStep(human)
    if not human.db.guide then 
        return 0
    end
    return human.db.guide.step or 0
end

function setGuideStep(human, step, sid)
    if not human.db.guide then 
        return 
    end
    human.db.guide.step = step
    if sid then
        --Log.write(Log.LOGID_OSS_GUIDE_SUB, human.db._id, human.db.account, human.db.name, human.db.lv, human.db.ip, human.pf or "", human.appid, sid)
        Log.write(Log.LOGID_OSS_GUIDE_SUB, human.db._id, human.db.newUniqueTag, human.db.name, human.db.lv, human.db.ip, human.pf or "", human.appid, sid)
    end
end

-- 
function setLoginStep(human, id)
    human.guideLoginStep = nil
    local cf = GuideExcel.main_guide[id]
    if not cf then return end
    if #cf.loginList < 1 then return end

    human.guideLoginStep = {}
    for i, sid in ipairs(cf.loginList) do
        human.guideLoginStep[i] = sid
    end
end

function getLoginStep(human)
    if not human.guideLoginStep then
        return 
    end
    return human.guideLoginStep[1]
end

function delLoginStep(human)
    if not human.guideLoginStep then return end

    for i = 1, #human.guideLoginStep do
        human.guideLoginStep[i] = human.guideLoginStep[i + 1]
    end
    if #human.guideLoginStep < 1 then
        human.guideLoginStep = nil
    end
end

-- 根据cmd获取id
function getGuideIDByCmd(human, cmd)
    if not human.db.guide or
        not human.db.guide.cmd2id then 
        return GUIDEID_FIRST
    end 
    if not human.db.guide.cmd2id[cmd] then
        return GUIDEID_FIRST
    end 
    return human.db.guide.cmd2id[cmd]
end

function isFinishGuideID(human, id)
    local cf = GuideExcel.main_guide[id]
    if not cf then return end

    local nowid = getGuideIDByCmd(human, cf.cmd)
    if nowid ~= id then
        return nowid > id
    end
    if getGuideID(human) == id then
        local state = getGuideState(human)
        return state == STATE_FINISH
    end
    return true
end

-- 获取当前类型 是否满足条件
function getGuideSkip(human, skipType)
    local id = getGuideID(human) 
    local state = getGuideState(human)
    if id and state == STATE_FINISH then
       return true
    end

    local cf = GuideExcel.main_guide[id]
    if not cf then return end
    if cf.skipType ~= skipType then return true end

    local isJump = nil    
    if cf.skipType == SKIPTYPE_JUMP then
        isJump = true
    elseif cf.skipType == SKIPTYPE_JUMP_DRAW or
        cf.skipType == SKIPTYPE_JUMP_HERO or 
        cf.skipType == SKIPTYPE_JUMP_SHOPBUY or
        cf.skipType == SKIPTYPE_JUMP_BATTLE or
        cf.skipType == SKIPTYPE_JUMP_JIEFENG_BAOJU or
        cf.skipType == SKIPTYPE_JUMP_BATTLE_GUAJI or 
        cf.skipType == SKIPTYPE_JUMP_BATTLE_EXP or
        cf.skipType == SKIPTYPE_JUMP_BARTASK then 
        if getDoSpecialGuide(human, cf.skipType) > 0 then
            isJump = true
        end
    elseif cf.skipType == SKIPTYPE_JUMP_NAME then
        if (human.db.changeNameCnt or 0) > 0 then
            isJump = true
        end
    
    elseif cf.skipType == SKIPTYPE_JUMP_HEROUP or 
           cf.skipType == SKIPTYPE_JUMP_UPGRADE then
        if getDoSpecialGuide(human, cf.skipType) >= cf.skipArgs[1] then
            isJump = true
        end 
    elseif cf.skipType == SKIPTYPE_JUMP_BATTLE_REWARD then        
        if BattleLogic.isGetReward(human, cf.skipArgs[1] or 1) then
            isJump = true
        end
    elseif cf.skipType == SKIPTYPE_JUMP_OL_REWARD then
        if (human.db.onlineReward and human.db.onlineReward.id or 1) > 1 then
            isJump = true
        end
    elseif cf.skipType == SKIPTYPE_JUMP_LOGINSIGN then
        if not LoginSignLogic.isRed(human) or getDoSpecialGuide(human, cf.skipType) > 0 then
            isJump = true
        end
    elseif cf.skipType == SKIPTYPE_JUMP_BATTLE_SD then
        if (human.db.mopupDoCnt or 0) > 0 and getDoSpecialGuide(human, cf.skipType) > 0 then
            isJump = true
        end
    elseif cf.skipType == SKIPTYPE_JUMP_LEVEL_GIFT then
        if human.db.chongJi ~= nil then
            isJump = true
        end
    elseif cf.skipType == SKIPTYPE_JUMP_OPEN_SERVER_GIFT then
        local len = #OpenActExcel.openServerGift
        for i = 1,len do
            local state = OpenServerGiftLogic.getGiftState(human, i)
            if state ~= 1 and state ~= 0 then
                isJump = true 
                break
            end
        end
    elseif cf.skipType == SKIPTYPE_JUMP_JIBAN_GROUP then
        for i = 1,CombatDefine.COMBAT_TYPE_MAX do
	        local combatHeroDB = CombatPosLogic.getCombatHeroDB(human,i)
            if combatHeroDB and combatHeroDB.jiban then
                isJump = true
                break
            end
        end
    end

    return isJump
end


-- 是否触发过该特殊指引
function getDoSpecialGuide(human, id)
    if not human.db.guide or 
        not human.db.guide.flags then   
        return 0
    end
    return human.db.guide.flags[id] or 0
end

-- 设置已触发
function setDoSpecialGuide(human, id)
    human.db.guide = human.db.guide or {}
    human.db.guide.flags = human.db.guide.flags or {}
    local cnt = human.db.guide.flags[id] or 0
    human.db.guide.flags[id] = cnt + 1
end

-- 刷新指引状态
function refreshGuide(human, isLogin)
    local id = getGuideID(human) 
    local state = getGuideState(human)
    if id and state ~= STATE_FINISH then
        local conf = GuideExcel.main_guide[id]
        if not conf then
            assert(nil, "  GuideExcel conf not  have id  : ".. id)
        end
        if conf.cmd == GUIDECMD_LIST[1] and conf.skipType == SKIPTYPE_JUMP_FINISH and isLogin then
           -- 完成此任务
           setGuide(human, id, STATE_FINISH, conf.skipType)
   
           while true do
               local pid = getGuideIDByCmd(human, GUIDECMD_LIST[1])
               if pid == GUIDEID_FIRST then
                  break
               end


               local nid = getNextGuideID(pid, GUIDECMD_LIST[1])
               local cf = GuideExcel.main_guide[nid]
               if nid and cf and cf.cmd == GUIDECMD_LIST[1] then
                  setGuide(human, nid, STATE_FINISH, cf.skipType)
               else
                  break
               end
           end
           
        end
        return
    end


    local doSkip = false
    local fid = nil
    for _, cmd in ipairs(GUIDECMD_LIST) do
        local cond, skip, nid = nil
        while true do
           local pid = getGuideIDByCmd(human, cmd)
           nid = getNextGuideID(pid, cmd)
           cond = checkCondition(human, nid)
           local cf = GuideExcel.main_guide[nid]
                                      
           if nid and cf and cf.cmd == "lv" then
               -- 不重登的情况下 必须达成等级需求才跳过 没有开启活动
               local isSkip = false
               if cf.args[2] == 1 and not isLogin and human.db.lv >= cf.args[1] and not cond then
                   setGuide(human, nid, STATE_FINISH, cf.skipType)
                   isSkip = true
               end
               -- 重登的情况下 直接跳过
               if isLogin and human.db.lv >= cf.args[1] then
                  setGuide(human, nid, STATE_FINISH, cf.skipType)
                  isSkip = true
               end

               if not isSkip then break end
           else
               break 
           end           
        end

        if nid and cond then
            fid = nid
            break
        end
    end
    if (not fid) or (fid == id) then return end

    setGuide(human, fid, STATE_DOING)
    return true 
end

-- 指引跳过/还原处理
function skipGuide(human)
    local id = getGuideID(human) 
    local state = getGuideState(human)
    if id and state == STATE_FINISH then
        return
    end
    local cf = GuideExcel.main_guide[id]
    if not cf then return end

    local isJump = nil    
    if cf.skipType == SKIPTYPE_JUMP or
       cf.skipType == SKIPTYPE_JUMP_BARTASK then
        isJump = true
    elseif cf.skipType == SKIPTYPE_JUMP_DRAW or
        cf.skipType == SKIPTYPE_JUMP_HERO or 
        cf.skipType == SKIPTYPE_JUMP_SHOPBUY or
        cf.skipType == SKIPTYPE_JUMP_BATTLE or
        cf.skipType == SKIPTYPE_JUMP_JIEFENG_BAOJU or
        cf.skipType == SKIPTYPE_JUMP_BATTLE_GUAJI or
        cf.skipType == SKIPTYPE_JUMP_BATTLE_EXP then 
        if getDoSpecialGuide(human, cf.skipType) > 0 then
            isJump = true
        end
    elseif cf.skipType == SKIPTYPE_JUMP_NAME then
        if human.db.changeNameCnt ~= nil then
            isJump = true
        end
    
    elseif cf.skipType == SKIPTYPE_JUMP_HEROUP or 
           cf.skipType == SKIPTYPE_JUMP_UPGRADE then
        if getDoSpecialGuide(human, cf.skipType) >= cf.skipArgs[1] then
            isJump = true
        end 
    elseif cf.skipType == SKIPTYPE_JUMP_BATTLE_REWARD then        
        if BattleLogic.isGetReward(human, cf.skipArgs[1] or 1) then
            isJump = true
        end
    elseif cf.skipType == SKIPTYPE_JUMP_OL_REWARD then
        if (human.db.onlineReward and human.db.onlineReward.id or 1) > 1 then
            isJump = true
        end
    elseif cf.skipType == SKIPTYPE_JUMP_LOGINSIGN then
        if not LoginSignLogic.isRed(human) or getDoSpecialGuide(human, cf.skipType) > 0 then
            isJump = true
        end
    elseif cf.skipType == SKIPTYPE_JUMP_BATTLE_SD then
        if (human.db.mopupDoCnt or 0) > 0 and getDoSpecialGuide(human, cf.skipType) > 0 then
            isJump = true
        end
    elseif cf.skipType == SKIPTYPE_JUMP_LEVEL_GIFT then
        if human.db.chongJi ~= nil then
            isJump = true
        end
    elseif cf.skipType == SKIPTYPE_JUMP_OPEN_SERVER_GIFT then
        local len = #OpenActExcel.openServerGift
        for i = 1,len do
            local state = OpenServerGiftLogic.getGiftState(human, i)
            if state ~= 1 and state ~= 0 then
                isJump = true 
                break
            end
        end
    elseif cf.skipType == SKIPTYPE_JUMP_JIBAN_GROUP then
        for i = 1,CombatDefine.COMBAT_TYPE_MAX do
	        local combatHeroDB = CombatPosLogic.getCombatHeroDB(human,i)
            if combatHeroDB and combatHeroDB.jiban then
                isJump = true
                break
            end
        end
    end
    if isJump then
        --跳过所有战斗
        for i = CombatDefine.COMBAT_TYPE1,  CombatDefine.COMBAT_TYPE_MAX do
	       CombatLogic.clientFinish(human, i, true)
        end
        return setGuide(human, id, STATE_FINISH, cf.skipType)
    end
    setGuideStep(human, nil)
end

---------------------------- condition -----------------------------------
GuideCondition = {}
GuideCondition["lv"] = function(human, lv, checkAct)
    if not SceneHandler.canCharge(human) then
        return -- 如果不能充值，所有等级指引都不开
    end

    if checkAct and checkAct == 1 then
       if human.db.lv >= lv then
          for k, v in ipairs(OpenActExcel.openAct) do
             local flag = OpenAct.getOpenActTime(k)
             if flag == true then
                return true
             end
          end
       end
    else
       return human.db.lv >= lv
    end

    return false
end

-- 完成指定战役
GuideCondition["battle"] = function(human, id)
    return (human.db.battleID or 1) > id
end

function checkCondition(human, id)
    local cf = GuideExcel.main_guide[id]
    if not cf then return end
    if cf.cmd == "" then return true end
    local func = GuideCondition[cf.cmd]
    if not func then return end
    return func(human, cf.args[1], cf.args[2])
end

------------------------------ excel --------------------------------------

-- 获取下一个指引id
local GUIDEID_2_NEXTID = nil    -- [cmd][preid] = nextid
function getNextGuideID(id, cmd)
    if not GUIDEID_2_NEXTID then
        GUIDEID_2_NEXTID = {}
        local sids = {}
        for tid, cf in Util.pairsByKeys(GuideExcel.main_guide) do
            if #cf.guideList > 0 then
                local sid = sids[cf.cmd] or GUIDEID_FIRST
                GUIDEID_2_NEXTID[cf.cmd] = GUIDEID_2_NEXTID[cf.cmd] or {}
                GUIDEID_2_NEXTID[cf.cmd][sid] =  tid 
                sids[cf.cmd] = tid 
            end
        end
    end
    if not GUIDEID_2_NEXTID[cmd] then
        return
    end
    return GUIDEID_2_NEXTID[cmd][id]
end

local SID_2_GUIDEID = nil
local SID_2_GUIDESTEP = nil
function getGuideIDBySid(sid)
    if not SID_2_GUIDEID then
        SID_2_GUIDEID = {}
        SID_2_GUIDESTEP = {}
        for id, cf in pairs(GuideExcel.main_guide) do
            for step, tsid in ipairs(cf.guideList) do
                SID_2_GUIDEID[tsid] = id
                SID_2_GUIDESTEP[tsid] = step
            end
        end        
    end
    return SID_2_GUIDEID[sid], SID_2_GUIDESTEP[sid]
end

function getNextGuideIDByLv(lv)
    local minlv = nil
    local minid = nil
    for id, cf in pairs(GuideExcel.lv_guide) do
        if cf.cmd == "lv" and cf.dialog > 0 then
            local clv = cf.args[1]
            if clv > lv and (minlv == nil or clv < minlv) then
                minlv = clv 
                minid = id
            end
        end
    end    
    if not minid then return end
    return minid
end

local DIALOG_2_CONTENT = nil
function getContentByDialog(dialog)
    if not dialog then return end
    if not DIALOG_2_CONTENT then
        DIALOG_2_CONTENT = {}
        for id, cf in pairs(GuideExcel.main_guide) do
            if cf.dialog > 0 then
                DIALOG_2_CONTENT[cf.dialog] = cf.content
            end
        end
    end
    return DIALOG_2_CONTENT[dialog]
end

local function getLvUpGetZuanshi(oldLv,newLv)
    local addZuanshi = 0
    for lv=1,#RoleExcel.exp do
        if lv > oldLv and lv <= newLv then
            addZuanshi = addZuanshi + RoleExcel.exp[lv].lvUpGetZuanshi
        end
    end

    return addZuanshi
end

------------------------------- msg -------------------------------------

function sendStep(human, sendNil)
    if not Config.HAS_GUIDE then return end -- 指引总开关
    local diffTime = os.time() - human.db.createTime
    if diffTime >= 7 * 86400 and human.db.lv >= 5 then
       return
    end

    if human.db.noguide and not sendNil then return end
    local id = (not sendNil) and getGuideID(human)
    local cf = id and GuideExcel.main_guide[id]
    local nextstep = getGuideStep(human) + 1
    local state = getGuideState(human)

    local msgRet = Msg.gc.GC_GUIDE_STEP
    msgRet.step[0] = 0
    if cf and state == STATE_DOING then
        local sid = getLoginStep(human) or cf.guideList[nextstep]
        local scf = sid and GuideExcel.sub_guide[sid]
        if scf then
            msgRet.step[0] = msgRet.step[0] + 1
            local net = msgRet.step[msgRet.step[0]]
            net.id = sid 
            net.conditions = Json.Encode(scf.conditions)
            net.behavior = Json.Encode(scf.behavior)
            net.sound = scf.sound
            net.dialog = scf.dialog
            net.content = scf.content
            net.handid = scf.handid
            net.zhiyin = scf.zhiyin
            net.heroLhID = scf.herolhId
            net.skip = scf.skip
            if scf.behavior[1] == "openPanel" and scf.behavior[2] and
                scf.behavior[2][1] == PanelDefine.PANEL_ID_52 then
                local dialog = scf.behavior[2][2]
                net.content = getContentByDialog(dialog)
            end

            if scf.behavior[1] == "showAnima" and GUIDE_COMBAT_INFO.combat ~= nil then
               CombatLogic.sendCombatData(human, GUIDE_COMBAT_INFO.combat)
            end
        end
    end
    --Msg.trace(msgRet)
    Msg.send(msgRet, human.fd)    
end

-- 能否下一步
function canStepFinish(human, sid)
    local state = getGuideState(human)
    if state ~= STATE_DOING then return end
    if getLoginStep(human) == sid then -- 登录步骤
        delLoginStep(human)
        return true, getGuideID(human), 0
    end
    local id, step = getGuideIDBySid(sid)
    if not id then return end
    if getGuideID(human) ~= id then return end

    if sid >= 503 and sid <= 506 then
        local config = GuideExcel.main_guide[id]
        local oldStep = getGuideStep(human)
        local oldSid = config.guideList[oldStep]
        if oldSid < 502 or oldSid > 506 then
            return 
        end
       -- if oldStep <
    else
        if getGuideStep(human) + 1 ~= step then return end
    end
   

    local cf = GuideExcel.main_guide[id]
    -- 升级次数
    if cf.skipType == SKIPTYPE_JUMP_HEROUP and cf.skipArgs[2] == sid then
        if getDoSpecialGuide(human, SKIPTYPE_JUMP_HEROUP) < cf.skipArgs[1] then
            return
        end
    end

    -- 进阶次数判定
    if cf.skipType == SKIPTYPE_JUMP_UPGRADE and cf.skipArgs[2] == sid then
        if getDoSpecialGuide(human, SKIPTYPE_JUMP_UPGRADE) < cf.skipArgs[1] then
            return
        end
    end   
    return true, id, step
end

function stepFinish(human, sid, noSend)
    local isok, id, step = canStepFinish(human, sid)
    if isok then
        local cf = GuideExcel.main_guide[id]
        if step >= #cf.guideList then
            setGuide(human, id, STATE_FINISH)
        else
            setGuideStep(human, step, sid)
	        MainDianLogic.MaiDian_Begin(human, MaiDianDefine.MAIDIAN_TYPE_GUIDE, {nValue = sid})
        end
    end

    if sid == GUIDEID_SPECIALSID then
        sendjumpinfo(human)
    else
        refreshGuide(human)
        sendStep(human)
    end
end

-- 登录回调
function onLogin(human)
    skipGuide(human)
    refreshGuide(human, true)
    if getGuideState(human) == STATE_DOING then
        setLoginStep(human, getGuideID(human))
        sendStep(human)
    end
    sendLvGuide(human)

    if human.db.lv and human.db.lv <= 4 then
        local nID = getGuideID(human)
        local nMaxID = 0
        for i, v in pairs(GuideExcel.main_guide) do
            nMaxID = math.max(nMaxID, i)
        end

        if nMaxID ==  nID then
            local tMsgData = Msg.gc.GC_GUIDE_WENJUAN_JUMPOK
            Msg.send(tMsgData, human.fd)    
        end
    end
end




-- 升级回调
function onLvUpCB(human, oldLv, newLv)
    local giveZuanshi = getLvUpGetZuanshi(oldLv,newLv)
    if giveZuanshi > 0 then
        ObjHuman.addZuanshi(human, giveZuanshi, "level_up")
    end

    local id = getNextGuideIDByLv(newLv)
    local cf = id and GuideExcel.lv_guide[id]
    local msgRet = Msg.gc.GC_LEVEL_UP
    local net = msgRet.data
    net.oldLv = oldLv
    net.newLv = newLv
    net.items[0] = 0
    if giveZuanshi > 0 then
        net.items[0] = net.items[0] + 1
        Grid.makeItem(net.items[net.items[0]], ItemDefine.ITEM_ZUANSHI_ID, giveZuanshi)
    end
    net.dialog = cf and cf.dialog or 0
    net.dialogName = cf and cf.dialogName or ""
    net.content = cf and cf.content or ""
    net.noticeLv = cf and cf.args[1] or 0
    net.panelId = cf and cf.panelId or 0
    Msg.send(msgRet, human.fd)
end

-- 等级指引
local function makeLvGuideNet(net, id, human)
    local cf = GuideExcel.lv_guide[id]
    net.id = id
    net.noticeLv = cf and cf.args[1] or 0
    net.panelId = cf and cf.panelId or 0
    net.status = human.db.lvGuide and human.db.lvGuide[id] or 0

    local len = 0 
    for k, v in ipairs(cf.guideList) do
       len = len + 1
       net.guideList[len] = v
    end
    net.guideList[0] = len
end

--推送等级指引
function sendLvGuide(human)
   local msgRet = Msg.gc.GC_LEVEL_GUIDE
   local len = 0
   for k, v in ipairs(GuideExcel.lv_guide) do
       len = len + 1
       local net = msgRet.data[len]
       makeLvGuideNet(net, k, human)
   end
   msgRet.data[0] = len
   Msg.send(msgRet, human.fd)
end

-- 
function stepLvFinish(human, id)
    local cf = GuideExcel.lv_guide[id]
    if not cf then
       if human.db.lvGuide and human.db.lvGuide[id] then
          human.db.lvGuide[id] = nil
       end
       return 
    end
    human.db.lvGuide = human.db.lvGuide or {}
    human.db.lvGuide[id] = 1
end

--
function stepLvInfo(human, id, guideId)
    if not Config.HAS_GUIDE then return end -- 指引总开关
    local diffTime = os.time() - human.db.createTime
    if diffTime >= 7 * 86400 and human.db.lv >= 5 then
       return
    end
  
    local cf = id and GuideExcel.lv_guide[id]
    if not cf then return end

    local msgRet = Msg.gc.GC_GUIDE_STEP
    msgRet.step[0] = 0

    local scf = GuideExcel.sub_guide[guideId]
    if scf then
        msgRet.step[0] = msgRet.step[0] + 1
        local net = msgRet.step[msgRet.step[0]]
        net.id = guideId 
        net.conditions = Json.Encode(scf.conditions)
        net.behavior = Json.Encode(scf.behavior)
        net.sound = scf.sound
        net.dialog = scf.dialog
        net.content = scf.content
        net.handid = scf.handid
        net.zhiyin = scf.zhiyin
        net.heroLhID = scf.herolhId
        net.skip = scf.skip
        
        if scf.behavior[1] == "openPanel" and scf.behavior[2] and
            scf.behavior[2][1] == PanelDefine.PANEL_ID_52 then
            local dialog = scf.behavior[2][2]
            net.content = getContentByDialog(dialog)
        end
    end
   
    Msg.send(msgRet, human.fd)    
end

-- 通用回调
function onCallback(human)
    if not refreshGuide(human) then
        return
    end

    if getGuideState(human) ~= STATE_DOING then
        return
    end

    sendStep(human)
    return true  
end 

-- 临时 容错
function checkAllFinish(human)
    if not Config.HAS_GUIDE then return 1 end 
 --   local lastConfig = GuideExcel.main_guide[1200]
--    local lastID = lastConfig.guideList[#lastConfig.guideList]

  --  local isFinish = isFinishGuideID(human, 1200)

    return isFinishGuideID(human, 1200) and 1 or 0
end

function stepwenjuanchose(human, szChoseID)
    local tChoseID = Util.split(szChoseID, "|")
    local bJump = false
    if tChoseID and nil ~= _G.next(tChoseID) then
        for _, key in ipairs(tChoseID) do
            local nID = tonumber(key)
            if GuideJumpExcel.Jump[nID] and GuideJumpExcel.Jump[nID].bJump 
                and GuideJumpExcel.Jump[nID].bJump == 1 then
                    bJump = true
                    break
            end
        end
    end

    if not human.db.bGetJumpPrize then
        local tPrize = GuideJumpExcel.Prize[1].tPrize
        BagLogic.addItemList(human, tPrize, "guide")
        
        human.db.bGetJumpPrize = true
    end

    if true == bJump and not FORCE_GUIDE_CHANNEL_LIST[human.phpChanelID] then
        local nMaxID = 0
        for nID, v in pairs(GuideExcel.main_guide) do
            nMaxID = math.max(nMaxID, nID)
        end

        print("[stepwenjuanchose] 设置完成主线 nMaxID = "..nMaxID)
        setGuide(human, nMaxID, STATE_FINISH)

        local tMsgData = Msg.gc.GC_GUIDE_WENJUAN_JUMPOK
        Msg.send(tMsgData, human.fd)

        ObjHuman.save(human)
    else
        refreshGuide(human)
        sendStep(human)
    end
end