
/*=============================================================================================
	author:ZhaoJun
	version:1.2
	email:2732810281@qq.com
=============================================================================================*/


//严格模式
/*-------------------------------------------------------------------------------------------*/	
'use strict';
/*-------------------------------------------------------------------------------------------*/
const net=require("net");	
const dgram = require('dgram');
const packages=$Sys.model('/socket/package')
const coms=$Sys.model('/load/com')

// tcp请求操作
/*-------------------------------------------------------------------------------------------*/	
    class tu
    {

		static com(pool,key,index,con,type,tag)
		{
			let dataMessage='data'
			if(tag)dataMessage='message'
			
			let curObj=$ExtendPool[type]

			function backFun(d,info)
			{
				if(d===$ExtendNet.heartTag)
				{
					if($ExtendNet.twHeartPrint)console.info('客户端收到心跳包')
					return
				}

				try 
				{
					d=JSON.parse(d)

					if($ExtendPool.funList.length)
					{
						for (let index = 0; index < $ExtendPool.funList.length; index++) 
						{
							let cur=$ExtendPool.funList[index]
							let key=cur.key
							if(d[key]==cur.eq && cur.fun)
							{
								let tag=cur.fun(d)
								if(tag)break
							}
						}
					}
					
					let map=curObj.data[d.$unique]
					if(map)
					{
						
						map.res(d,info);
					}
					else if(con.dataBack)
					{
						con.dataBack(d,info)
					}
				} 
				catch (error) 
				{
					console.warn(`[${type}客户端]解析错误`,error)
					console.log(d,d.length)
					return
				}
			}

			if(pool)
			{
				// 接收消息
				con.str=''
				con.on(dataMessage, function (d,info) 
				{
					d=d.toString()
					if(type==='tcp')
					{
						let list=packages.decode.call(con,d)
						for (let index = 0; index < list.length; index++) 
						{
							let cur=list[index]
							backFun(cur,info)
						}
					}
					else
					{
						backFun(d,info)
					}
				})
			}

			con.sender=function(data,ty={})
			{
				if(tag)
				{
					let buf=Buffer.isBuffer(data)
					if(!buf)data=Buffer.from(data)
					return con.send(data,0,data.length,ty.$port,ty.$ip)
				}
				else if(con.writable)
				{
					if(ty.encode)data=packages.encode(data)
					return con.write(data);
				}
				else
				{
					return false;
				}
			}


			con.json=function(data,ty)
			{
				if(data instanceof Object)
				{
					return con.sender(JSON.stringify(data),ty)
				}
			}


			con.on('close',function()
			{
				if(pool)pool[key].map[index]=null
				console.warn(`[${type}连接]`,'关闭');
			})

			//错误处理
			con.on('error', function (error) 
			{
				console.error(`[${type}连接]错误------`,`描述：${e.stack}`);
			})



		}

		static tcpCon(opt,pool,key,index,tag,type,reslove,reject)
		{
			var NET_CLI=net.createConnection
			(
				opt,function ()
				{
					NET_CLI.initCount=0
					NET_CLI.unref();
					NET_CLI.setNoDelay(true);
					
					reslove(NET_CLI)
					
					if(tag)console.info('[TCP连接]','重连成功');
				}
			);

			NET_CLI.setEncoding('utf8')

			tu.com(pool,key,index,NET_CLI,type)

		}

		static udpCon(opt,pool,key,index,tag,type,reslove,reject)
		{

			var UDP_CLI = dgram.createSocket('udp4'); 
			
			reslove(UDP_CLI)
			if(tag)console.info('[TCP连接]','重连成功');
			tu.com(pool,key,index,UDP_CLI,type,true)

		}

        static connect(opt,pool,key,index,tag,type='tcp')
        {
			return new Promise
			(
				function(reslove,reject)
				{
					if(type=='tcp')return tu.tcpCon(opt,pool,key,index,tag,type,reslove,reject)
					else if(type=='udp') return tu.udpCon(opt,pool,key,index,tag,type,reslove,reject)
				}
			)
		}

		
		static async init(opt=$ExtendPool.tcp.opt,type='tcp') 
		{
			for (const key in opt) 
			{
				let cur=opt[key]
				let count=0;
				let curArr=[]
				let pool

				if(type=='tcp')
				{
					for (let index = 0; index < cur.length; index++) 
					{
						let curr=cur[index]
						curr.weight=curr.weight?curr.weight:1
						let optSub={host:curr.host,port:curr.port}
						for (let index = 0; index < curr.weight; index++) 
						{
							count+=1
							curArr.push(optSub)
						}
					}
	
					pool=function(index,tag)
					{
						return tu.connect(curArr[index],$ExtendPool.tcp.pool,key,index,tag,type)
					}   

					console.info(`TcpPool-${key}初始化中: 请等待...`); 
					await tu.pools(count,pool,key,type)
					console.info(`TcpPool-${key}初始化完成: 总共${count}个连接`);

				}
				else if(type=='udp')
				{
					count=cur.count

					let optList=$ExtendPool.udp.opt.rpc.list
					let arr=[]
					if(optList)
					{
						for (let index = 0; index < optList.length; index++) 
						{
							let cur=optList[index]
							let optSub={host:cur.host,port:cur.port}
							if(cur.weight)
							{
								for (let index = 0; index < cur.weight; index++) 
								{
									arr.push(optSub)
								}
							}
							else
							{
								arr.push(optSub)
							}
						}
						$ExtendPool.udp.opt.rpc.list=arr
					}

					pool=function(index,tag)
					{
						return tu.connect(undefined,$ExtendPool.udp.pool,key,index,tag,type)
					}   

					console.info(`UdppPool-${key}初始化中: 请等待...`); 
					await tu.pools(count,pool,key,type)
					console.info(`UdppPool-${key}初始化完成: 总共${count}个连接`);
				} 

			}
		}

		static async pools(count,pool,key,type)
		{
			let poolw=$Sys.model('/fun/pool')
			$ExtendPool[type].pool[key]=await new poolw
			(
				count,pool,result=>
				{

					if(!result)return

					result.con.initCount+=1
					if(result.con.initCount==3)
					{
						result.con.initCount=0;
						result.con.sender($ExtendNet.heartTag+$ExtendNet.package.end.init)	
					}
					return result
				}
			)
		}

    }
/*-------------------------------------------------------------------------------------------*/    
module.exports=tu;
