local global = _G.global

local Log = require("common.Log")
local Lang  = require("common.Lang")
local MiddleFilter = require("common.MiddleFilter")
local InnerMsg = require("core.InnerMsg")
local Broadcast = require("broadcast.Broadcast")

MONITOR_ENABLE = false

MONITOR_PACKET = MONITOR_PACKET or {}	-- 用户包相关
MONITOR_TIMER = MONITOR_ADMIN or {}		-- 定时器相关
MONITOR_CUSTOM = MONITOR_CUSTOM or {}	-- 自定制
MONITOR_INNER_PACKET = MONITOR_INNER_PACKET or {} -- 内部通信协议相关

local handleTime1 = nil
local handleTime2 = nil

local Msg = require("core.Msg")
function handlePacket(human, container, protoId)
	if _G.is_middle then -- 跨服功能受限于白名单配置
		if not MiddleFilter.isPermit(protoId) then
			if type(human) == "table" then
				Broadcast.sendErr(human, Lang.MIDDLE_CG_NOT_IN_WHITE .. " " .. protoId)
			end
			return
		end
	else
		-- 处于跨服中，本服功能部分屏蔽
		if type(human) == "table" and human.db and human.db.middleFlag then
			if not MiddleFilter.isPermit(protoId) then
				Broadcast.sendErr(human, Lang.MIDDLE_CG_NOT_IN_WHITE2 .. " " .. protoId)
				return
			end
		end
	end

	if MONITOR_ENABLE then
		MONITOR_PACKET[0] = MONITOR_PACKET[0] or {0, 0}
		MONITOR_PACKET[protoId] = MONITOR_PACKET[protoId] or {0, 0}
		handleTime1 = global.get_usec()
	end
	
	-- 调试日志：检查 CG_DRILL_ONE_CLICK_SAODANG 协议
	-- if protoId == 1748 or Msg.proto_name[protoId] == "CG_DRILL_ONE_CLICK_SAODANG" then
	-- 	Log.write(Log.LOGID_DEBUG, "[Monitor.handlePacket] 收到 CG_DRILL_ONE_CLICK_SAODANG 协议, protoId="..protoId..", handler存在="..tostring(Msg.proto_handler[protoId] ~= nil))
	-- end
	
	if not Msg.proto_handler[protoId] then
		-- Log.write(Log.LOGID_DEBUG, "[Monitor.handlePacket] WARNING: protoId="..protoId.." 没有对应的handler, protoName="..tostring(Msg.proto_name[protoId]))
		return
	end
	
	Msg.proto_handler[protoId](human, container)
	
	if MONITOR_ENABLE then
		handleTime2 = global.get_usec()
		MONITOR_PACKET[0][1] = MONITOR_PACKET[0][1] + 1							-- 包量
		MONITOR_PACKET[0][2] = MONITOR_PACKET[0][2] + handleTime2 - handleTime1 -- 处理时间
		
		MONITOR_PACKET[protoId][1] = MONITOR_PACKET[protoId][1] + 1
		MONITOR_PACKET[protoId][2] = MONITOR_PACKET[protoId][2] + handleTime2 - handleTime1
	end	
end

function handleTimer(func, t, key)
	if MONITOR_ENABLE then
		handleTime1 = global.get_usec()
	end
    
	func(t)
	
	if MONITOR_ENABLE then
		MONITOR_TIMER[0] = MONITOR_TIMER[0] or {0, 0}
		MONITOR_TIMER[key] = MONITOR_TIMER[key] or {0, 0}
		
		handleTime2 = global.get_usec()		
		
		MONITOR_TIMER[0][1] = MONITOR_TIMER[0][1] + 1
		MONITOR_TIMER[0][2] = MONITOR_TIMER[0][2] + handleTime2 - handleTime1
		
		
		MONITOR_TIMER[key][1] = MONITOR_TIMER[key][1] + 1
		MONITOR_TIMER[key][2] = MONITOR_TIMER[key][2] + handleTime2 - handleTime1
	end
end

local InnerMsg = require("core.InnerMsg")
function handleInnerPacket(fd, container, protoId)
	if MONITOR_ENABLE then
		MONITOR_INNER_PACKET[0] = MONITOR_INNER_PACKET[0] or {0, 0}
		MONITOR_INNER_PACKET[protoId] = MONITOR_INNER_PACKET[protoId] or {0, 0}
		handleTime1 = global.get_usec()
	end
  
	InnerMsg.proto_handler[protoId](fd, container)
  
	if MONITOR_ENABLE then
		handleTime2 = global.get_usec()
		MONITOR_INNER_PACKET[0][1] = MONITOR_INNER_PACKET[0][1] + 1             -- 包量
		MONITOR_INNER_PACKET[0][2] = MONITOR_INNER_PACKET[0][2] + handleTime2 - handleTime1 -- 处理时间
	    
		MONITOR_INNER_PACKET[protoId][1] = MONITOR_INNER_PACKET[protoId][1] + 1
		MONITOR_INNER_PACKET[protoId][2] = MONITOR_INNER_PACKET[protoId][2] + handleTime2 - handleTime1
	end 
end

custom_table_temp = custom_table_temp or {}
function custom1(key)
	if not MONITOR_ENABLE then return end
	custom_table_temp[key] = global.get_usec()
end

function custom2(key)
	if not MONITOR_ENABLE then return end
	
	MONITOR_CUSTOM[key] = MONITOR_CUSTOM[key] or {0, 0}
	local time2 = global.get_usec()
	
	MONITOR_CUSTOM[key][1] = MONITOR_CUSTOM[key][1] + 1
	MONITOR_CUSTOM[key][2] = MONITOR_CUSTOM[key][2] + time2 - custom_table_temp[key]
end

local function cmp(a, b)
	return a[3] > b[3]
end

local function getThreadDesc()
	if _G.is_middle then
		return "middle"
	end
	return "logic"
end

local tempTable = {}
local function writeLog(monitor_name, monitor_list, see_count)
	for k in pairs(tempTable) do
		tempTable[k] = nil
	end
	local tempCount = 0
	for k, v in pairs(monitor_list) do
		tempCount = tempCount + 1
		tempTable[tempCount] = {k, v[1], v[2]}
	end	
	for k in pairs(monitor_list) do
		monitor_list[k] = nil
	end
	if tempCount > 1 then
		table.sort(tempTable, cmp)
	end

	if not see_count or tempCount > 0 then
		local str = monitor_name .. getThreadDesc()
		for i = 1, tempCount do
			if i > 7 then break end
			str = str .. " key:" .. tempTable[i][1] .. " c:" .. tempTable[i][2] .. " t:" .. tempTable[i][3]
		end
		Log.write(Log.LOGID_MONITOR, str)
	end
end

function output()
	if not MONITOR_ENABLE then return end

	writeLog("TIMER:", MONITOR_TIMER)
	writeLog("IO:", MONITOR_PACKET)
	writeLog("INNER:", MONITOR_INNER_PACKET)
	writeLog("CUSTOM:", MONITOR_CUSTOM, true)
end
