{% extends 'base.html' %}

{#
	Eos - Verifiable elections
	Copyright © 2017-18  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">
	<link rel="stylesheet" href="{{ url_for('static', filename='bower_components/progress-tracker/app/styles/progress-tracker.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>
	{% if eosweb.app.config['CAST_FINGERPRINT'] %}
		<script src="{{ url_for('static', filename='bower_components/fingerprintjs2/dist/fingerprint2.min.js') }}"></script>
	{% endif %}
	
	<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 }};
		var should_do_fingerprint = {{ 'true' if eosweb.app.config['CAST_FINGERPRINT'] else 'false' }};
		
		function resetBooth() {
			booth = {
				"questionNum": 0,
				"answers": [],
				"q_state": [],
				"fingerprint": []
			};
		}
		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"
					})
						.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.kind }}. Please try again. If this problem persists, contact the {{ election.kind }} 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.kind }} administrator.</p>' + techDetails + '</div>');
			console.error(err);
		}
		
		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;
		
		if (location.search.indexOf('?prepoll') >= 0) {
			// Pre-poll
			boothTasks.append({
				activate: function(fromLeft) {
					showTemplate('booth/review_prepoll.html', {ballot: booth.ballot});
				}
			});
			templates['booth/review_prepoll.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_prepoll.html', {ballot: booth.ballot});
				}
			});
			templates['booth/cast_prepoll.html'] = null;
		} else {
			// Real voting booth
			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 %}