{% extends 'base.html' %}

{#
	Eos - Verifiable elections
	Copyright © 2017  RunasSudo (Yingtong Li)
	
	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU Affero General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.
	
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Affero General Public License for more details.
	
	You should have received a copy of the GNU Affero General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
#}

{% block title %}{{ election.name }} – Voting booth{% endblock %}

{% block head %}
	{{ super() }}
	<link rel="stylesheet" href="{{ url_for('static', filename='bower_components/dragula.js/dist/dragula.min.css') }}" type="text/css">
{% endblock %}

{% block content %}
	<div class="ui container" id="booth-content">
		<div class="ui active text loader">Loading voting booth. Please wait.</div>
	</div>
{% endblock %}

{% block basecontent %}
	{{ super() }}
	
	<script src="{{ url_for('static', filename='bower_components/nunjucks/browser/nunjucks.min.js') }}"></script>
	<script src="{{ url_for('static', filename='js/eosjs.js') }}"></script>
	
	<script src="{{ url_for('static', filename='bower_components/dragula.js/dist/dragula.min.js') }}"></script>
	
	<script>
		var templates = {};
		var election = null;
		var booth = null;
		var boothWorker = null;
		var boothTasks = [];
		var currentBoothTask = 0;
		var selection_model_view_map = {{ selection_model_view_map|safe }}; {# :rooWut: #}
		
		var username = {% if session.user %}"{{ session.user.name }}"{% else %}null{% endif %};
		var auth_methods = {{ auth_methods|safe }};
		
		function resetBooth() {
			booth = {
				"questionNum": 0,
				"answers": [],
			};
		}
		resetBooth();
		
		function loadElection() {
			$.ajax({ url: "{{ url_for('election_api_json', election_id=election._id) }}", dataType: "text" })
				.done(function(data) {
					try {
						election = eosjs.eos.core.objects.__all__.EosObject.deserialise_and_unwrap(eosjs.eos.core.objects.__all__.EosObject.from_json(data), null);
						
						boothWorker = new Worker("{{ url_for('static', filename='js/booth_worker.js') }}");
						
						electionLoaded();
					} catch (err) {
						loadError(err);
						throw err;
					}
				})
				.fail(function(xhr, status, err) {
					loadError(err);
					throw err;
				});
		}
		
		function electionLoaded() {
			// Load templates for the question types
			for (var i = 0; i < election.questions.__len__(); i++) {
				var question = election.questions.__getitem__(i);
				templates[selection_model_view_map[question._name]['selections_make']] = null;
				templates[selection_model_view_map[question._name]['selections_review']] = null;
			}
			
			loadTemplates();
		}
		
		function loadTemplates() {
			// Load all the templates
			var templateUrls = Object.keys(templates);
			var numTemplatesLoaded = 0;
			for (var templateUrl of templateUrls) {
				(function(templateUrl) {
					$.ajax({
						url: "{{ url_for('static', filename='nunjucks') }}/" + templateUrl,
						dataType: "text",
						cache: {% if eosweb.app.debug %}false{% else %}true{% endif %}
					})
						.done(function(data) {
							try {
								templates[templateUrl] = nunjucks.compile(data);
								numTemplatesLoaded += 1;
								if (numTemplatesLoaded == templateUrls.length) {
									// All templates loaded. Show voting booth
									boothTasks[0].activate(true);
								}
							} catch (err) {
								loadError(err);
								throw err;
							}
						})
						.fail(function(xhr, status, err) {
							loadError(err);
							throw err;
						});
				})(templateUrl);
			}
		}
		
		function loadError(err) {
			var techDetails = '';
			if (err) {
				techDetails = '<p>Technical details: ' + err + '</p>';
			}
			$("#booth-content").html('<div class="ui error message"><p>We were unable to load the voting booth for this election. Please try again. If this problem persists, contact the election administrator.</p>' + techDetails + '</div>');
		}
		
		function boothError(err) {
			resetBooth();
			var techDetails = '';
			if (err) {
				techDetails = '<p>Technical details: ' + err + '</p>';
			}
			$("#booth-content").html('<div class="ui error message"><p>We were unable to display the next page of the voting booth. For your security, your ballot selections have been cleared. Please try again. If this problem persists, contact the election administrator.</p>' + techDetails + '</div>');
		}
		
		function showTemplate(template, opts, destination) {
			try {
				if (!destination) {
					destination = "#booth-content";
				}
				if (!opts) {
					opts = {};
				}
				opts = $.extend({
					"templates": templates,
					"template": template,
					"election_base_url": "{{ url_for('election_api_json', election_id=election._id) }}",
					"static_base_url": "{{ url_for('static', filename='') }}",
					"election": election,
					"booth": booth,
					"eosjs": eosjs,
					"selection_model_view_map": selection_model_view_map,
					"username": username,
					"auth_methods": auth_methods
				}, opts);
				$(destination).html(templates[template].render(opts));
			} catch (err) {
				boothError(err);
				throw err;
			}
		}
		
		function nextTemplate(num) {
			if (!num) {
				num = 1;
			}
			currentBoothTask += num;
			boothTasks[currentBoothTask].activate(true);
		}
		
		function prevTemplate(num) {
			if (!num) {
				num = 1;
			}
			currentBoothTask -= num;
			boothTasks[currentBoothTask].activate(false);
		}
		
		// === BOOTH TASKS ===
		// TODO: Make modular
		
		boothTasks.append({
			activate: function(fromLeft) {
				showTemplate('booth/welcome.html');
			}
		});
		templates['booth/base.html'] = null;
		templates['booth/welcome.html'] = null;
		boothTasks.append({
			activate: function(fromLeft) {
				showTemplate('booth/selections.html');
			}
		});
		templates['booth/selections.html'] = null;
		boothTasks.append({
			activate: function(fromLeft) {
				if (fromLeft) {
					showTemplate('booth/encrypt.html');
				} else {
					prevTemplate();
				}
			}
		});
		templates['booth/encrypt.html'] = null;
		boothTasks.append({
			activate: function(fromLeft) {
				showTemplate('booth/review.html', {ballot: booth.ballot});
			}
		});
		templates['booth/review.html'] = null;
		boothTasks.append({
			activate: function(fromLeft) {
				showTemplate('booth/audit.html', {ballot: booth.ballot});
			}
		});
		templates['booth/audit.html'] = null;
		boothTasks.append({
			activate: function(fromLeft) {
				showTemplate('booth/cast.html', {ballot: booth.ballot});
			}
		});
		templates['booth/cast.html'] = null;
		boothTasks.append({
			activate: function(fromLeft) {
				showTemplate('booth/complete.html', {voter: booth.voter, vote: booth.vote});
			}
		});
		templates['booth/complete.html'] = null;
		
		// === END BOOTH TASKS ===
		
		loadElection();
	</script>
{% endblock %}