<!DOCTYPE html>
<head>
	<title>{{ model_name }} (Mesa visualization)</title>
  {% comment 
  The jquery.min.js supplied with this version of mesa  is downloaded from
  "ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js" Re-test mesa
  visulaizations when upgrading jquery to a newer version.
  %}
	<script src="/static/jquery.min.js"></script>
	<script src="/static/dat.gui.min.js"></script>
	<script>
	/*
		This is the Tornado template for the Modular Visualization. The Javascript code opens a WebSocket connection to the server 
		(the port is set via the template). On every step, it receives inputs, one per module, and sends them to the associated function to render

		Users can reset() the model, advance it by one step(), or run() it through. reset() and 
		step() send a message to the server, which then sends back the appropriate data. run() just
		calls the step() method at fixed intervals.

		The model parameters are controlled via the MesaVisualizationControl object. The GUI is 
		created using the dat.GUI library.
	
	*/
		/**
		Object which holds visualization parameters.
	
			tick: What tick of the model we're currently at
			running: Boolean on whether we have reached the end of the current model
			fps: Current frames per second.
		*/
		var MesaVisualizationControl = function() {
			this.tick = -1; // Counts at which tick of the model we are.
			this.running = false; // Whether there is currently a model running
			this.fps  = 3 ; // Frames per second
		}

		var player; // Variable to store the continuous player
		var control = new MesaVisualizationControl();
		var elements = [];  // List of Element objects


		// WebSocket Stuff
		var ws = new WebSocket("ws://127.0.0.1:{{ port }}/ws"); // Open the websocket connection
                ws.onopen = function() {
                    console.log("Connection opened!");
                    reset();
                };

		/**
		Parse an incoming message
		*/
		ws.onmessage = function(message) {
			msg = JSON.parse(message.data);
			//console.log(message.data);
			switch (msg["type"]) {
				case "viz_state":
					data = msg["data"]
					for (var i in elements) {
						elements[i].render(data[i]);
					}
					break;
				case "end":
					// We have reached the end of the model
					control.running = false;
					break;
				default:
					// There shouldn't be any other message
					console.log("Unexpected message.");
			}
		}
		
		/**
		Turn an object into a string to send to the server, and send it.
		*/
		var send = function(message) {
			msg = JSON.stringify(message);
			ws.send(msg);
		}

		/**
		Reset the model, and rest the appropriate local variables.
		*/
		var reset = function() {
			control.tick = 0;
			send({"type": "reset"});

			// Reset all the visualizations
			for (var i in elements) {
				elements[i].reset();
			}
		};

		/**
		Send a message to the server get the next visualization state.
		*/

		var single_step = function() {
			control.tick += 1;
			send({"type": "get_step", "step": control.tick});
		};
		var step = function() {
			if (!control.running) {single_step()}
			else {run()};
		};
		/**
		Call the step function at fixed intervals, until getting an end message from the server.
		*/
		var run = function() {
			if (control.running) {
				control.running = false;
				runController.name("run");
				if (player) {
					clearInterval(player);
					player = null;
				}
			}
			else {
				control.running = true;
				runController.name("stop");
				player = setInterval(single_step, 1000/control.fps);
			}
		};
	</script>
	
</head>
<body>
	<h2>{{ model_name }}</h2> <!-- Template; put the model name as the heading -->


<!-- Script includes go here -->
	{% for file_name in package_includes %}
		<script src="/static/{{ file_name }}" type="text/javascript"></script>
	{% end %}
	{% for file_name in local_includes %}
		<script src="/local/{{ file_name }}" type="text/javascript"></script>
	{% end %}
<script>
	// Set up the GUI
	var gui = new dat.GUI();
	var fps_control = gui.add(control, "fps", 0, 20).step(1); // fps slider, 0 to 20 in 1 increments 
	// Create the buttons
	gui.add(this, "reset"); 
	gui.add(this, "step");
	var runController = gui.add(this, "run");

	/**
	Called when the user releases the fps slider; if already running, stop and
    start again to reset the fps
	*/
	fps_control.onFinishChange(function(value) {
		if (control.running) {
			run();
			run();
		}
	});

	// Element-specific scripts go here:
	// Actual script snippets go here.
	{% for script in scripts %}
			{% raw script %}
	{% end %}

</script>

</body>
