local NetworkManager = {}

local nHeartBeatTime = 25
--[[
    1. 心跳包要隔25s时间发送一次
    2. 两个周期没有收到即视为掉线
]]

-- local bShowReconnect = false

-- -- todo 不知道是在会议里还是会议外
-- local function CloseMeetingUI()
--     local uiHelper = require("Base/UIHelper.lua")
--     uiHelper:SwitchUI("UI/EnterMeeting/ZUIPanelEnterMeeting.lua", "UI/Meeting/ZUIPanelMeetingManager.lua")
--     uiHelper:CloseUI("UI/ZMeetingSceneManager.lua")
--     bShowReconnect = false
-- end

-- local function ReConnectServer()
--     if bShowReconnect then
--         return
--     end

--     bShowReconnect = true
--     ShowDialogOK("NetworkManager", "与服务器连接断开, 请重试", CloseMeetingUI)
-- end

local function ConnectServer(serverIP, serverPort)
    local connectState = CS.LuaSocketManager.Connect(serverIP, serverPort)
    NetworkManager.connectState = connectState
    return connectState
end

local function ConnectLogicCoroutine()
    print("----> ConnectLogicCoroutine:")

    -- local serverIP = "192.168.3.248" -- longyue
    -- local serverPort = 9205
    -- local serverIP = "192.168.0.55" -- server
    local serverIP = "192.168.0.200" -- server
    local serverPort = 9206

    local eventManager = require("Base/ZEventDispatchCenter.lua")
    require("Base/CoroutineHelper.lua"):WaitForEndOfFrame()

    local hasFailed = false
    local condition = false
    while condition == false do
        -- todo 不能用这个判断是否链接上服务器了
        local connectState = SafeCall(ConnectServer, serverIP, serverPort)
        NetworkManager.connectState = connectState

        if not connectState then
			print(string.format(
				"NetworkManager.ConnectLogicCoroutine ConnectServer(%s:%s) Failed. Retry after 5s:",
				serverIP, serverPort, connectState
			))
            eventManager:DispatchEvent(eventManager.EventType.NET_CONNECT_STATE, false)
            hasFailed = true
            require("Base/CoroutineHelper.lua"):Wait(5)
        end
        condition = connectState == true
    end

    print(string.format( "NetworkManager.ConnectLogicCoroutine ConnectServer(%s:%s) Success!", serverIP, serverPort))
    if hasFailed == true then
	    -- todo
        -- local languageConfig = require("Config/SConfigManager.lua"):GetConfig("languageConfig")
        -- ShowDialogOK(languageConfig["login"]["connect_success"])
        -- eventManager:DispatchEvent(eventManager.EventType.NET_CONNECT_STATE, true)
    end

    require("Network/NetworkQueue.lua"):Reset()
end

local function RecvlogicCoroutine()
    while true do
		require("Base/CoroutineHelper.lua"):Wait(0.1)
        local connectState = CS.LuaSocketManager.Update()
        NetworkManager.connectState = connectState

        -- todo 待办
        if not connectState then
            -- 断线重连
            return
        end

		local serverMessage = CS.LuaSocketManager.RecvMessage()

		-- if serverMessage ~= nil and serverMessage.msgType and serverMessage.msgData then
		while serverMessage ~= nil and serverMessage.msgType and serverMessage.msgData do
            print("----> serverMessage.msgData", serverMessage.msgData)

			local serverProtocol = NetworkManager._jsonConvert:decode(serverMessage.msgData)
			-- local processorName = serverMessage.msgType
            -- print("----> processorName:", processorName)
			-- if not processorName then print("Get processorName Failed for: ", serverMessage) end

			local msgType = NetworkManager._s2c[serverMessage.msgType]
			if not msgType then
                print("Get msgType failed for : " , serverMessage.msgType, "  ", serverMessage.msgData)
            end

            -- local NetworkQueue = require("Network/NetworkQueue.lua")
            -- NetworkQueue:PushMsgOnRecv(tonumber(serverMessage.requestNumber), {serverMessage.msgType, serverProtocol})
            -- local data = NetworkQueue:TryPopMsg()
            -- while data ~= nil do
            --     local func = NetworkManager._s2c[data[1]]
            --     func(NetworkManager._s2c, data[2])
            --     data = NetworkQueue:TryPopMsg()
            -- end

            msgType(NetworkManager._s2c, serverProtocol)
		    serverMessage = CS.LuaSocketManager.RecvMessage()
		end
	end
end

local function HeartBeatCoroutine()
    local nMaxCount = 3
    local eventManager = require("Base/ZEventDispatchCenter.lua")

    while true do
        require("Network/C2S.lua"):HeartBeat()

        require("Base/CoroutineHelper.lua"):Wait(nHeartBeatTime)
        local nHeartBeat = require("Base/DataRelay.lua"):GetCache("HEART_BEAT", 0)
        nHeartBeat = nHeartBeat + 1

        if nHeartBeat >= nMaxCount then
            require("Base/CoroutineHelper.lua"):Stop(NetworkManager._heartBeatCorutine)
            -- todo 用户掉线
        end
    end
end

local function InitScoketInfo()
    CS.ZLog.Options.Instance.LogLevel = 2
    CS.ZLog.Log.Debug("")
end

function NetworkManager:Init()
    print("NetworkManager.Init~")

    InitScoketInfo()

    self._c2s = require("Network/C2S.lua")
    self._s2c = require("Network/S2C.lua")

    self._connectLogicCoroutine = require("Base/CoroutineHelper.lua"):Start(ConnectLogicCoroutine)

    self._recvlogicCoroutine    = require("Base/CoroutineHelper.lua"):Start(RecvlogicCoroutine)
    self._jsonConvert           = require("Base/json.lua")
    self._eventManager          = require("Base/ZEventDispatchCenter.lua")

    -- 心跳
    self._heartBeatCorutine  = require("Base/CoroutineHelper.lua"):Start(HeartBeatCoroutine)
end

function NetworkManager:UnInit()
    require("Base/CoroutineHelper.lua"):Stop(NetworkManager._connectLogicCoroutine)
    require("Base/CoroutineHelper.lua"):Stop(NetworkManager._recvlogicCoroutine)
    -- 心跳
    require("Base/CoroutineHelper.lua"):Stop(NetworkManager._heartBeatCorutine)

    CS.LuaSocketManager.Disconnect()
    print("NetworkManager.UnInit ~")
end

function NetworkManager:RemoteCall(funcName, ... )
    print("NetworkManager:RemoteCall funcName:", funcName, " param:", ...)
	self._c2s:RemoteCall(funcName, ...)
end

return NetworkManager