import * as LogAbstract from "@terrencecrowley/logabstract";
import * as Context from "@terrencecrowley/context";

interface TestEnv { context: Context.IContext, log: LogAbstract.ILog };

import * as OT from "../lib/all";
import * as OTTestClient from "./ottestclient";
import * as OTTestServer from "./ottestserver";

export namespace test {

	// function: test_server
	//
	// Description:
	//	Simulate a set of clients and servers
	//

	// Inclusive of nMin, nMax
	function randomWithinRange(nMin: number, nMax: number): number
		{
			return nMin + Math.floor(Math.random() * (nMax - nMin + 1));
		}

	export function test_server(env: TestEnv): void
		{
			const NClients: number = 10;
			const NTicks: number = 1000;

			env.log.log("===Server Test===");
			let server: OTTestServer.OTTestServer = new OTTestServer.OTTestServer(env);
			let clients: OTTestClient.OTTestClient[] = [];

			for (let i: number = 0; i < NClients; i++)
			{
				let c = new OTTestClient.OTTestClient(env, String(i));
				clients.push(c);
				server.addClient(c);
			}

			for (let i: number = 0; i < NTicks; i++)
			{
				let n: number = randomWithinRange(0, NClients);
				if (n == NClients)
					server.tick();
				else
					clients[n].tick();
			}

			server.drain();

			let serverVal: any = server.toValue();
			let clientVal: any;
			let nFail: number = 0;
			for (let i: number = 0; i < NClients; i++)
			{
				clientVal = clients[i].toValue();
				if (serverVal['text'] != clientVal['text'])
				{
					nFail++;
					env.log.log("Server Test: Client " + i + " does not match server.");
				}
			}
			if (nFail == 0)
				env.log.log("Server Test: success");
		}

	export function tests(): Array<(env: TestEnv) => void> {
		let a = [ test.test_server ];
		return a;
	}
};
