"use strict";

//! {"description": "Massively multiplayer online Turtle Graphics"}

// This script runs server-side, once for each client session.

if (imports.terminal) {
	terminal.setEcho(false);
	terminal.split([
		{
			type: "horizontal",
			children: [
				{name: "graphics", basis: "700px", shrink: "0", grow: "0"},
				{name: "text"},
			],
		},
	]);

	// Request a callback every time the user hits enter at the terminal prompt.
	core.register("onInput", function(input) {
		// Ask a persistent service session to broadcast our message.  We'll also get a copy back.
		return core.getService("turtle").then(function(service) {
			return service.postMessage(input);
		});
	});

	// Request a callback for every message that is broadcast.
	core.register("onMessage", function(sender, message) {
		if (message.history) {
			for (var i = 0; i < message.history.length; i++) {
				// Pass the message on to the iframe in the client.
				terminal.postMessageToIframe("turtle", message.history[i]);
			}
		} else {
			// Pass the message on to the iframe in the client.
			terminal.postMessageToIframe("turtle", message);
		}
	});

	core.register("onWindowMessage", function(data) {
		if (data.message.ready) {
			core.getService("turtle").then(function(service) {
				return service.postMessage("sync");
			});
		} else {
			terminal.print(data.message);
		}
	});

	terminal.select("graphics");
	terminal.print("MMO Turtle Graphics using ", {href: "http://codeheartjs.com/turtle/"}, ".");

	// Add an iframe to the terminal.  This is how we sandbox code running on the client.
	var contents = `
	<script src="https://codeheart.williams.edu/turtle/turtle.min.js">-*- javascript -*-</script>
	<script>
	setScale(2);
	setWidth(3);

	// Receive messages in the iframe and use them to draw.
	function onMessage(event) {
		var parts = event.data.split(" ");
		var command = parts.shift();
		if (command == "reset") {
			setPosition(0, 0);
			setHeading(0);
			clear(WHITE);
			_ch_startTimer(30);
		} else if (command == "home") {
			var wasDown = _turtle.penDown;
			pu();
			setPosition(0, 0);
			setHeading(0);
			if (wasDown) {
				pd();
			}
			_ch_startTimer(30);
		} else if (command == "clear") {
			clear(WHITE);
			_ch_startTimer(30);
		} else if (["fd", "bk", "rt", "lt", "pu", "pd", "setColor", "setWidth"].indexOf(command) != -1) {
			window[command].apply(window, parts.map(parseFloat));
			event.source.postMessage(event.data, event.origin);
			_ch_startTimer(30);
		} else {
			event.source.postMessage("Unrecognized command: " + command, event.origin);
		}
		if (_turtle.nextCommandIndex >= _turtle.commandBuffer.length) {
			_turtle.nextCommandIndex = 0;
		}
	}

	function onLoad() {
		parent.postMessage({ready: true}, "*");
	}

	// Register for messages in the iframe
	window.addEventListener('message', onMessage, false);

	window.addEventListener('load', onLoad, false);
	</script>
	`
	terminal.print({iframe: contents, width: 640, height: 480, name: "turtle"});

	terminal.select("text");
	terminal.print("Supported commands: ", ["fd <distance>", "bk <distance>", "rt <angle>", "lt <angle>", "pu", "pd", "home", "reset", "clear"].join(", "));
} else {
	var gHistory = null;

	function ensureHistoryLoaded() {
		if (!gHistory) {
			return database.get("history").then(function(data) {
				gHistory = JSON.parse(data);
				return gHistory;
			}).catch(function(error) {
				gHistory = [];
				return gHistory;
			});
		} else {
			return new Promise(function(resolve, reject) { resolve(gHistory); });
		}
	}

	core.register("onMessage", function(sender, message) {
		return ensureHistoryLoaded().then(function(history) {
			if (message == "reset") {
				history.length = 0;
				database.set("history", JSON.stringify(history));
				return core.broadcast(message);
			} else if (message == "sync") {
				sender.postMessage({history: history});
			} else {
				history.push(message);
				database.set("history", JSON.stringify(history));
				return core.broadcast(message);
			}
		});
	});
}