local RoleSystemExcel = require("excel.roleSystem")
local Util = require("common.Util")
local Lang = require("common.Lang")
local CommonDB = require("common.CommonDB")
local Msg = require("core.Msg")
local ObjHuman = require("core.ObjHuman")
local Broadcast = require("broadcast.Broadcast")
local DrillLogic = require("drill.DrillLogic")
local ZhuanpanExcel = require("excel.zhuanpan")
local RoleSystemDefine = require("roleSystem.RoleSystemDefine")
local RoleOpenPrize = require("roleSystem.RoleOpenPrize")
local BagLogic = require("bag.BagLogic")


DOUBLE_NEED_LV = 10 -- 福利双倍 开启等级

--邮件提示ID
ROLE_MAILTIPS_ID1 = 1  --圣树试炼 


ROLE_SYS_OPEN_ID_START = 1  --
ROLE_SYS_OPEN_ID_END = 50 --

local function initDB(human)
   human.db.roleSys = human.db.roleSys or {}
end

function initAfterHot() 
	for id, conf in pairs(RoleSystemExcel.roleSystem) do 
		conf.id = id
        if conf.modulePath == "" then
		
		else
			conf.module = load("return require(\""..conf.modulePath.."\")")()
		end
	end
end

function isOpen(human, id, sendErr)
	local config = RoleSystemExcel.roleSystem[id]
	if not config then
		return
	end

	-- 开服天数
	if config.openSvrDay > 0 then
		local openDay = CommonDB.getServerOpenDay()
		if not openDay then
			if sendErr then
				Broadcast.sendErr(human, Lang.COMMON_SYSTEM_NEED_OPENTIME)
			end
			return false, config
		end
		if openDay < config.openSvrDay then
			if sendErr then
				Broadcast.sendErr(human, Util.format(Lang.COMMON_SYSTEM_OPENTIME, config.openSvrDay))
			end
			return false, config
		end
	end
	
	-- 等级
	if human.db.lv < config.lv then 
		if sendErr then
			Broadcast.sendErr(human, Util.format(Lang.COMMON_SYSTEM_OPENTIP, config.lv))
		end
		return false, config
	end
    -- 寻星
    if id == RoleSystemDefine.ROLE_SYS_ID_501 then
        local now = os.time()
        local zpOpenTime = os.time(ZhuanpanExcel.define[1].time)
        if now < zpOpenTime then
            return false
        end
    end

	--战令, 临时处理下, 如果多了再优化成通用方法
	if id == RoleSystemDefine.ROLE_SYS_ID_2005 then
		local WarOrder = require("shop.WarOrder")
		local res = WarOrder.isOpen(human)
		if not res then
			return false, config
		end
	else
		if config.module and config.module.ModuleisOpen then
			local bOpen = config.module.ModuleisOpen(human)
			if not bOpen then
				return false, config
			end
		end
	end

	return true, config
end

-- 等级达到x级
ROLE_SYSTEM_OPEN_NEED_LV = {}
function getOpenLv(id)
	if ROLE_SYSTEM_OPEN_NEED_LV[id] then
		return ROLE_SYSTEM_OPEN_NEED_LV[id]
	end

	local config = RoleSystemExcel.roleSystem[id]
	if config then
		ROLE_SYSTEM_OPEN_NEED_LV[id] = config.lv
		return  ROLE_SYSTEM_OPEN_NEED_LV[id]
	end
	return 0
end

-- 开服x天后开启
function getOpenSvrDay(id)
	local config = RoleSystemExcel.roleSystem[id]
	if config.openSvrDay > 0 then
		local openDay = CommonDB.getServerOpenDay()
		if not openDay or openDay < config.openSvrDay then
			return config and config.openSvrDay or 0
		end
	end
	return 0
end

-- 获取开启条件说明
function getOpenDesc(id)
	local config = RoleSystemExcel.roleSystem[id]
	if not config then return "" end
	if config.lv >= 999 then
		return Lang.COMMON_SYSTEM_READY
	end
	if config.openSvrDay > 0 and config.lv > 1 then
		return Util.format(Lang.COMMON_SYSTEM_OPENLV_TIME, config.lv, config.openSvrDay)
	end
	if config.openSvrDay > 0 then
		return Util.format(Lang.COMMON_SYSTEM_OPENTIME, config.openSvrDay)
	end
	return Util.format(Lang.COMMON_SYSTEM_OPENTIP, config.lv)
end

-- 不发送客户端
local function isNoSend(id)
	return id > 10000 
end

-- 是否有红点
local function isDot(human,config)
    if human.db.lv < config.dotLv then
       return false
    end

	-- 幽暗禁地红点判断：检查是否有至少1种卷（1034、1035、1036）的数量≥20
	if config.id == RoleSystemDefine.ROLE_SYS_ID_1215 then
		local itemIds = {1034, 1035, 1036}
		for _, itemId in ipairs(itemIds) do
			local cnt = BagLogic.getItemCnt(human, itemId)
			if cnt >= 20 then
				return true
			end
		end
		return false
	end

	if config.module and config.module.isDot and config.module.isDot(human,config) then
		return true
	end
	return false
end

function touch(human, id)
   local roleExcel = RoleSystemExcel.roleSystem[id]
   if not roleExcel then return end
   if roleExcel.touch ~= 1 then return end
   local touch = human.db.roleSys[id]
   if not touch then return end
   human.db.roleSys[id] = 0
   onDot(human, id, true)
end


function open(human, id)
   if not human.db.roleSysOpen then
      human.db.roleSysOpen = {}
   end
   local len = #human.db.roleSysOpen
   if  len >= ROLE_SYS_OPEN_ID_END then return end

   len = len + 1
   human.db.roleSysOpen[len] = id
end

-- 封装结构体
local function wrapAll(human, mem, net, config)
	mem[config.id] = false

	net.id = config.id
	net.lv = getOpenLv(config.id)
	net.needDay = getOpenSvrDay(config.id)
	net.lockType = config.lock
    net.name = config.name
    net.desc = config.desc
    net.doubleDay = config.doubleDay
    net.doubleDesc = config.doubleDesc
    net.panelID = config.panelID or 0
    net.dobule = isDouble(human, config.id) and 1 or 0
    net.touch = 0
	net.isShow = config.isdisplay or 0
    
	if isOpen(human,config.id) then
		net.isOpen = 1	
        if config.touch == 1 then
           human.db.roleSys[net.id] = human.db.roleSys[net.id] or 1
           net.touch = human.db.roleSys[net.id]
        end
        
		if isDot(human,config) == true then
			mem[config.id] = true
			net.dot = 1
		else
			mem[config.id] = false
			net.dot = 0
		end
	else
		net.isOpen = 0
		net.dot = 0
	end
end

local function sendSystemAll(human)
    if not human.roleSystem then return end

    initDB(human)
	local msgRet = Msg.gc.GC_ROLESYSTEM_QUERY
	local len = 0
	local mem = human.roleSystem
	for id, config in pairs(RoleSystemExcel.roleSystem) do
		if not isNoSend(id) then
			len = len + 1
			local net = msgRet.list[len]
			wrapAll(human,mem,net,config)
		end
	end
	msgRet.list[0] = len
	Msg.send(msgRet,human.fd)
end

function senddSysemOpen(human)
   if not human.db.roleSysOpen then return end
   local msgRet = Msg.gc.GC_ROLESYSTEM_OPEN
   local len = 0
   for _, v in pairs(human.db.roleSysOpen) do
   	  len = len + 1
   	  msgRet.id[len] = v
   end	   
   msgRet.id[0] = len
   Msg.send(msgRet,human.fd)
end

local function sendSystemSingle(human, id)
	local config = RoleSystemExcel.roleSystem[id]
	if config == nil then
		return
	end
	if isNoSend(id) then return end
	
	local msgRet = Msg.gc.GC_ROLESYSTEM_QUERY
	local mem = human.roleSystem
	local net = msgRet.list[1] 
	wrapAll(human,mem,net,config)
	msgRet.list[0] = 1
	Msg.send(msgRet,human.fd)
end

function onLogin(human)
	human.roleSystem = human.roleSystem or {}
	sendSystemAll(human)
    senddSysemOpen(human)
	RoleOpenPrize.RoleSystem_CheckPrize(human)
end

function onLvUp(human)
	sendSystemAll(human)
	RoleOpenPrize.RoleSystem_CheckPrize(human)
end

function onDotByUuid(uuid, id)
	local human = ObjHuman.onlineUuid[uuid]
	if human and human.fd then
		onDot(human, id)
	end
end

function onDot(human,id, noSend, bForceSend)
	if isOpen(human,id) ~= true and not bForceSend then
		return
	end

	human.roleSystem = human.roleSystem or {}
	
	local oldDotStatus =  human.roleSystem[id]
	local config = RoleSystemExcel.roleSystem[id]
	local newDotStatus = isDot(human,config)
	if oldDotStatus ~= newDotStatus then
		sendSystemSingle(human, id)
	end

    if noSend then
       sendSystemSingle(human, id)
    end
end

--是否关闭
function isClose(human,id)
	if not isOpen(human, id) then
		sendSystemSingle(human, id)
	end
end

-- 是否有双倍
function isDouble(human, id)
	if human.db.lv < DOUBLE_NEED_LV then return false end
    local config = RoleSystemExcel.roleSystem[id]
    if not config then return end

    local doubleDay = config.doubleDay
    if doubleDay == 0 then return end

    local weekDay = Util.getWeekDay()
    if doubleDay == weekDay then 
       return true
    end
	return false
end

function checkMailTips(human)
    DrillLogic.sendDrillTip(human)
end

function checkOpenByID(human, nID)

	local bOpen = isOpen(human, nID)
	if not bOpen then
		return false
	end

	return bOpen
end