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


//严格模式
/*-------------------------------------------------------------------------------------------*/	
'use strict';
/*-------------------------------------------------------------------------------------------*/
const fs=require('fs')		
const process=require("process");
const os=require("os");
const dgram = require('dgram');
const cluster=require('cluster');

// 复用操作
/*-------------------------------------------------------------------------------------------*/	
	class com
	{
		static err()
		{	 
			function err(e)
			{
				console.error('发生了一个未捕捉错误进程:'+process.pid+'\r\n'+'未捕捉错误:',e);
				if($Config.coerrin>$Config.coerr)
				{
					console.error('意外错误次数过多,将重启进程:'+process.pid);
					var timeout=setTimeout
					(
						function ()
						{
							process.exit(1);
						},10000
					);
					timeout.unref();
				}
				$Config.coerrin+=1;
			}
			process.on('uncaughtException',err);
			process.on
			(
				'unhandledRejection', (reason, p) => 
				{
					err(reason)
				}
			);
			process.on
			(
				'rejectionHandled', (p) => 
				{
					err(p)
				}
			);
		}
		
		static async config()
		{
			let arr=await $Load.forFile($Config.root+'/nodejs/config')
			for (let df of arr) 
			{
				let conf=df.replace($Config.root+"/nodejs/config/","").replace(".cnf.js","")
				let confArr=conf.split('/')
				let conVar=''
				for (let iterator of confArr) 
				{
					let word=iterator.toUpperCase()
					conVar+=word[0]+iterator.slice(1)
				}
				let cnfName=df.replace(/.*\/(.*?)\.cnf\.js$/,'$1')
				conVar='$'+conVar

				


				if(cnfName!='config')
				{
					global[conVar]=require(df)
					// if(cnfName=='$Code')
					// {
					// 	global[conVar]=new Proxy
					// 	(
					// 		require(df),
					// 		{  
					// 			get(target, key) 
					// 			{ 
					// 				return {...target[key]};
					// 			} 
					// 		} 
					// 	)
					// }
					// else
					// {
					// 	global[conVar]=require(df)
					// }
				}
				if(typeof cnfVar == 'object')Object.seal(global[conVar]);
			}
		}

		static info()
		{
			let ipMac=os.networkInterfaces();


			/*
				address: '192.168.1.108',
				netmask: '255.255.255.0',
				family: 'IPv4',
				mac: '01:02:03:0a:0b:0c',
				internal: false,
				cidr: '192.168.1.108/24'
				name:'本地连接'
			*/
            let arr=[]
            for (const key in ipMac) 
            {
                let cur=ipMac[key]
                for (let index = 0; index < cur.length; index++) 
                {
					let _cur=cur[index]
					if(_cur.mac=='00:00:00:00:00:00')continue
                    _cur.name=key
                    arr.push(_cur)
                }
			}

			/*
			'aix'
			'darwin'
			'freebsd'
			'linux'
			'openbsd'
			'sunos'
			'win32'
			*/
			
			$Config.info.ipMac=arr
			$Config.info.platform=os.platform()
			$Config.info.pid=process.pid

		}
		
		static async start(opt)
		{	
			let cur=process.version.replace('v','').split('.')
			let mat=$Config.nodeVersion.split('.')
			for (let index = 0; index < cur.length; index++) 
			{
				let _cur=Number(cur[index])
				let _mat=Number(mat[index])
				if(_cur>_mat)
				{
					break;
				}
				else
				{
					console.error('版本必须大于',$Config.nodeVersion)
					process.exit(1)
				}
			}
			com.info()
			await com.config()

			if(!$Config.debug)com.err()
			
      		if($Config.multi)
			{
				if(cluster.isMaster)
				{  
					console.info("CLUSTER模式------初始化中");
					await require($Config.root+'/nodejs/bootstrap/master.js').start()
					var i=0;
					for(i=0;i<$Config.multi;i++)
					{
						cluster.fork();
					}	

					cluster.on
					(
						'exit',function (w,a)
						{
							cluster.fork();
							console.error('服务重启');
						}
					);
				}
				else
				{
					await require($Config.root+'/nodejs/bootstrap/cluster.js').start()
					com.cal(opt);
				}
			}
			else
			{
				console.info("ALONE模式------初始化中");
				await require($Config.root+'/nodejs/bootstrap/alone.js').start()
				com.cal(opt);
			}
    }

		static cal(opt)
		{
			//中间件
			$Sys.middle('/index','include')()
			if(opt['http'])
			{
				com.http(opt['http']);
			}
			if(opt['http2'])
			{
				com.http2(opt['http2']);
			}
			if(opt['tcp'])
			{
				com.tcp(opt['tcp']);
			}
			if(opt['websocket'])
			{
				com.ws(opt['websocket']);
			}	
			if(opt['websockets'])
			{
				com.wss(opt['websockets']);
			}	
			if(opt['udp'])
			{
				com.udp(opt['udp']);
			}	
		}
		static udpConfig(server)
		{
			let udp=$ExtendNet.udp
			if(udp.multi)
			{
				server.addMembership(udp.multiAddr);
				server.setMulticastTTL(udp.multiTtl);
				server.setMulticastLoopback(udp.multiLoop)
			}

			server.setTTL(udp.ttl);
			server.setRecvBufferSize(udp.recv)
			server.setSendBufferSize(udp.send)
		}

		static udp(port)
		{
			const server = dgram.createSocket('udp4');

			server.on
			(
				'listening',()=>
				{
					com.udpConfig(server)

					$ExtendNet.udp.server=server
					
					let method=$Sys.model('/load/init_s')
					new method(server,server,3)
				}
			);

			com.proCom(server,port,'UDP')
		}

		static http(port)
		{
			var http=require('http');
			
			var http_ser=http.createServer
			(
				(req,res)=>
				{
					com.httpCom(req,res,'http')
				}
			);

			com.proCom(http_ser,port,'HTTP')
		}

		static http2(port)
		{
			const { createSecureServer } = require('http2');
			const readFileSync  = fs.readFileSync;
			
			const cert = readFileSync($Config.cer);
			const key = readFileSync($Config.key);
			
			const http2_ser = createSecureServer
			(
				{ cert, key, allowHTTP1: true },
				(req, res)=> 
				{
					com.httpCom(req,res,'http2')
				}
			);
			com.proCom(http2_ser,port,'http2')
		}

		static tcp(port)
		{
			var net=require('net');

			var NET_SER=net.createServer
			(
				function(req)
				{
					req.on
					(
						'error',function(e)
						{
							let users=socket.$saveName?socket.$saveName.join(','):'';
							console.error(`TCP(${users})客户端错误报告来自初始化进程------描述：${e.stack}`);
						}
					)
					let method=$Sys.model('/load/init_s')
					new method(req,req,1)
				}
			);
			com.proCom(NET_SER,port,'TCP')
		}

		static ws(port)
		{
			var http=require('http');

			var WEB_SER=http.createServer();
			com.proCom(WEB_SER,port,'WS')
			com.wsCom(WEB_SER,'WS')
		}

		static wss(port)
		{
			const { createSecureServer } = require('http2');
			const readFileSync  = fs.readFileSync;


			const cert = readFileSync($Config.cer);
			const key = readFileSync($Config.key);
			
			const WEB_SER = createSecureServer({ cert, key, allowHTTP1: true });

			com.proCom(WEB_SER,port,'WSS')
			com.wsCom(WEB_SER,'WSS')
		} 

		static httpCom(req,res,tag)
		{
			req.on
			(
				'error',function(e)
				{
					console.error(tag+'客户端请求错误------'+`描述：${e.stack}`);
				}
			)
			res.on
			(
				'error',function(e)
				{
					console.error(tag+'服务端回复错误------'+`描述：${e.stack}`);
				}
			)
			$Sys.model('/load/init_h','route')(req,res);
		}

		static wsCom(ser,tag)
		{
			ser.on
			(
				'upgrade',function(req,socket)
				{
					socket.on
					(
						'error',function(e)
						{
							let users=socket.$saveName?socket.$saveName.join(','):'';
							console.error(`${tag}(${users})------客户端错误报告来自初始化进程------描述：${e.stack}`);
						}
					)
					req.on
					(
						'error',function(e)
						{
							console.error(tag+'客户端错误------'+`描述：${e.stack}`,1);
						}
					)
					let method=$Sys.model('/load/init_s')
					new method(socket,req,2)
				}
			)
		}
		static proCom(ser,port,tag)
		{
			if(!ser.bind)ser.bind=ser.listen
			ser.bind
			(
				port,'0.0.0.0',function()
				{
					console.info(tag+'进程：'+process.pid+'------'+`监听[${port}]`);
				}
			);

			ser.on
			(
				'close',function ()
				{
					console.warn(tag+'服务器关闭');
				}
			)

			ser.on
			(
				'error',function (e)
				{
					console.error(tag+'服务器错误------'+`描述：${e.stack}`);
				}
			);
		}
  }
/*-------------------------------------------------------------------------------------------*/    
module.exports=com;