'use strict'

const ws = require('ws')
const WebSocketServer = ws.Server
const config = require('./config')
const bluebird = require('bluebird')
const fs = require('fs')
const Router = require('./core/router')
const async = require('async')
const PlatformClass = require('./platforms/' + config.platform)
const errcode = require('./core/errcode')
const co = require('co')
const cluster = require('cluster')
const os = require('os')
const log = require('./core/log')
const utils = require('./core/utils')
const exec = require('child_process').exec

const promisify = [ 'fs', 'mongodb' ]
for (const moduleName of promisify)
{
	const module = require(moduleName)
	bluebird.promisifyAll(module)
}

class MetagameServer
{
	constructor()
	{
		this.log = log.create('server')
		this.platform = new PlatformClass()
	}
	
	*initWorker()
	{
		this.server = new WebSocketServer({
			port: config.websocket.port
		})
		
		const router = new Router(this.server)
		
		const servicesDir = './services/'
		const files = yield fs.readdirAsync(servicesDir)
		for (const file of files)
		{
			const serviceName = file.split('.')[0]
			const ServiceClass = require(servicesDir + serviceName)
			
			const serviceLogger = log.create(serviceName)
			const service = new ServiceClass({
				log: serviceLogger,
				platform: this.platform,
				router,
			})
			
			if (service.init)
			{
				yield service.init()
			}
			
			const routes = service.getRoutes()
			for (const route of routes)
			{
				const path = route[0]
				const handler = route[1].bind(service)
				let middleware = route[2]
				if (middleware)
				{
					middleware = middleware.map(func => func.bind(service))
				}
				router.addRoute(path, handler, middleware)
			}
		}
		
		router.start()
		this.log.info('init done')
	}
	
	*init()
	{
		if (cluster.isMaster && config.clustering.enabled)
		{
			const coreCount = os.cpus().length
			const workerCount = coreCount * config.clustering.workersPerCore
			this.log.info({ 
				coreCount,
				workerCount
			}, 'forking')
			
			for (let i = 0; i < workerCount; i++)
			{
				cluster.fork({ version: config.version })
			}
		}
		else
		{
			yield this.initWorker()
		}
	}
	
	close()
	{
		this.server.close()
	}
	
	get address()
	{
		return this.server._server.address()
	}
}

if (module.parent)
{
	module.exports = MetagameServer
}
else
{
	co(function*()
	{
		const server = new MetagameServer()
		yield server.init()
	}).catch(err => { throw err })
}
@@ -826,25 +826,34 @@
 )%0A%09%7B%0A%09%09this.
-s
+webSocketS
 erver = new 
@@ -905,24 +905,73 @@
 ort%0A%09%09%7D)%0A%09%09%0A
+%09%09this.httpServer = this.webSocketServer._server%0A
 %09%09const rout
@@ -987,25 +987,34 @@
 Router(this.
-s
+webSocketS
 erver)%0A%09%09%0A%09%09
@@ -2243,25 +2243,34 @@
 )%0A%09%7B%0A%09%09this.
-s
+webSocketS
 erver.close(
@@ -2312,17 +2312,13 @@
 his.
-server._s
+httpS
 erve

Store reference to http server