<?php

namespace App\Console\Commands;

use App\Classes\Protocol\Binkd;
use App\Classes\Protocol\EMSI;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;

use App\Classes\Sock\SocketException;
use App\Classes\Sock\SocketServer;

use App\Classes\Protocol\EMSI as EMSIClass;

class StartServer extends Command
{
	/**
	 * The name and signature of the console command.
	 *
	 * @var string
	 */
	protected $signature = 'server:start';

	/**
	 * The console command description.
	 *
	 * @var string
	 */
	protected $description = 'Start Server';

	/**
	 * Execute the console command.
	 *
	 * @return mixed
	 */
	public function handle()
	{
		// @todo This should be a config item.
		$start = [
			'emsi' => [
				'address'=>'0.0.0.0',
				'port'=>60179,
				'class'=>new EMSI,

			],
			'binkp' => [
				'address'=>'0.0.0.0',
				'port'=>24554,
				'class'=>new Binkd,
			],
		];

		$children = collect();

		Log::debug(sprintf('%s:+ Starting Servers...',__METHOD__));

		foreach ($start as $item => $config) {
			Log::debug(sprintf('%s:   - Starting: [%s]',__METHOD__,$item));

			$pid = pcntl_fork();

			if ($pid == -1)
				die('could not fork');

			// We are the child
			if (! $pid) {
				Log::info(sprintf('%s:   - Started: [%s]',__METHOD__,$item));

				$server = new SocketServer($config['port'],$config['address']);
				$server->setConnectionHandler([$config['class'],'onConnect']);

				try {
					$server->listen();

				} catch (SocketException $e) {
					if ($e->getMessage() == 'Can\'t accept connections: "Success"')
						Log::debug('Server Terminated');
					else
						Log::emergency('Uncaught Message: '.$e->getMessage());
				}

				Log::info(sprintf('%s:   - Finished: [%s]',__METHOD__,$item));

				// Child finished we need to get out of this loop.
				exit;
			}

			$children->put($pid,$item);
		}

		// Wait for children to exit
		while ($children->count()) {
			// Wait for children to finish
			$exited = pcntl_wait($status);

			Log::info(sprintf('%s:   - Exited: [%s]',__METHOD__,$children->pull($exited)));
		}

		// Done
		Log::debug(sprintf('%s:= Finished.',__METHOD__));
	}
}