{% extends 'base.html' %}
{% load custom_tags_and_filters %}
{% block title %}Calendar{% endblock %}
{% block extrahead %}
	{% load static %}
	<link rel="stylesheet" type="text/css" href="{% static "fullcalendar/fullcalendar.css" %}" />
	<script type="text/javascript" src="{% static "fullcalendar/fullcalendar.js" %}"></script>
{% endblock %}
{% block body %}

<div id="sidebar" class="application-sidebar">
	<div class="btn-group sidebar-item">
		<button type="button" class="btn btn-default dropdown-toggle" style="width:100%" data-toggle="dropdown">
			<span id="event_type">Reservations</span>
			<span class="caret"></span>
		</button>
		<ul class="dropdown-menu">
			<li class="dropdown-header">Which type of events would you like<br>to view on the calendar?</li>
			<li data-toggle="tooltip" data-placement="right" title="Displays {% if tools and areas %}tool and area{% elif tools %}tool{% elif areas %}area{% endif %} reservations. While viewing reservations, the 'Personal schedule' link shows your reservations for all {% if tools and areas %}tools and areas{% elif tools %}tools{% elif areas %}areas{% endif %}. Select a {% if tools and areas %}tool or area{% elif tools %}tool{% elif areas %}area{% endif %} to view everyone's reservations for that {% if tools and areas %}tool or area{% elif tools %}tool{% elif areas %}area{% endif %}."><a href="javascript:void(0)" onclick="change_calendar_event_type(this)">Reservations</a></li>
			<li data-toggle="tooltip" data-placement="right" title="Displays your {{ facility_name }} usage. This includes{% if areas %} area access,{% endif %}{% if tools %} tool usage,{% endif %} and missed reservations (which are all billable items)."><a href="javascript:void(0)" onclick="change_calendar_event_type(this)">{{ facility_name }} usage</a></li>
			{% if user.is_staff %}
				<li data-toggle="tooltip" data-placement="right" title="Displays {{ facility_name }} reservations and usage for a specific user. This includes reservations, area access, tool usage, and missed reservations."><a href="javascript:void(0)" onclick="change_calendar_event_type(this)">Specific user</a></li>
			{% endif %}
		</ul>
	</div>
	<div id="expand-collapse" class="btn-group sidebar-item">
		<button type="button" class="btn btn-default" style="width:50%" onclick="expand_all_categories()" title="Expand all categories"><span class="glyphicon glyphicon-resize-full"></span></button>
		<button type="button" class="btn btn-default" style="width:50%" onclick="collapse_all_categories()" title="Collapse all categories"><span class="glyphicon glyphicon-resize-small"></span></button>
	</div>
	<input type="text" id="item_search" placeholder="Search for{% if tools %} a tool{% endif %}{% if tools and areas %} or{% endif %}{% if areas %} an area{% endif %}" class="form-control sidebar-item" autocomplete="off">
	<input type="text" id="user_search" placeholder="Search for a user" class="form-control sidebar-item" autocomplete="off" style="display:none">
	<button id="chosen_user_button" type="button" class="btn btn-default" style="width:100%; display:none" onclick="clear_specific_user()"></button>

	{# The following menu tree code was take from an example at http://www.bootply.com/120625 #}
	<ul id="extra-links" class="nav nav-list" style="margin-top: 10px; margin-bottom: 8px;">
		<li><a href="javascript:void(0)" class="selected personal_schedule" data-item-id="personal_schedule" onclick="set_selected_item(this); update_event_sources()">Personal schedule</a></li>
		{% if calendar_all_tools %}
		<li><a href="javascript:void(0)" class="all_tools" data-item-id="all_tools" onclick="set_selected_item(this); update_event_sources()">All tools</a></li>
		{% endif %}
		{% if calendar_all_areas %}
		<li><a href="javascript:void(0)" class="all_areas" data-item-id="all_areas" onclick="set_selected_item(this); update_event_sources()">All areas</a></li>
		{% endif %}
		{% if calendar_all_areastools %}
		<li><a href="javascript:void(0)" class="all_areastools" data-item-id="all_areastools" onclick="set_selected_item(this); update_event_sources()">All areas and tools</a></li>
		{% endif %}
	</ul>
	{# The item tree has the HTML class tag "item_tree". See the widgets/item_tree.py file for more information. #}
	{{ rendered_item_tree_html }}
	<div style="height:50px"></div>
</div>

<div id="calendar" class="application-content"></div>
<input type="hidden" id="impersonate" name="impersonate" value="test">

<script type="text/javascript">
var logged_in = false;
{% if user.in_area %}
logged_in = "{{ user.area_access_record.area.name }}";
{% endif %}

function get_event_type()
{
	return $("#event_type").text().trim().toLowerCase();
}

function set_event_type(text)
{
	$("#event_type").html(text);
}

{# Check which tool/area we want to display information for and establish the calendar feed. #}
{# This function also checks if the user wishes to display their personal calendar feed (that is, all events #}
{# specific to them for all tools/areas). #}
function update_event_sources()
{
	{# Remove all event sources from the calendar. #}
	let calendar_jq = $("#calendar");
	calendar_jq.fullCalendar("removeEventSource", "{% url 'event_feed' %}");

	let event_type = get_event_type();
	let item_event_source =
	{
		url: "{% url 'event_feed' %}",
		data:
		{
			event_type: event_type
		}
	};

	if(event_type === 'reservations' || event_type === '{{ facility_name|lower }} usage')
	{
		let item = get_selected_item();
		let scheduled_outage_button = $(".fc-scheduledOutage-button")[0];
		$(scheduled_outage_button).addClass('fc-state-disabled');
		if(item === 'personal_schedule')
		{
			item_event_source.data.personal_schedule = true;
		}
		else if(item === 'all_tools')
		{
			item_event_source.data.all_tools = true;
		}
		else if(item === 'all_areas')
		{
			item_event_source.data.all_areas = true;
		}
		else if(item === 'all_areastools')
		{
			item_event_source.data.all_areastools = true;
		}
		else if(item)
		{
			item = JSON.parse(item)
			item_event_source.data.item_id = item.id;
			item_event_source.data.item_type = item.type;
			$(scheduled_outage_button).removeClass('fc-state-disabled');
		}
	}
	else if(event_type === 'specific user')
	{
		let user_search = $("#user_search");
		if(user_search.typeahead('val'))
			item_event_source.data.user = user_search.typeahead('val');
		else
			return;
	}

	calendar_jq.fullCalendar("addEventSource", item_event_source);

	refresh_sidebar_icons();
	refresh_calendar_login();
}

{# This function is a callback for when a reservation is successfully created by the user. #}
{# It renders the event to the calendar by refetching the event feed. #}
function event_creation_success_callback(response, status, xml_http_request, ajax_post, success_callback)
{
	$("#calendar").fullCalendar("unselect");
	{# If the response is empty then the reservation was successfully created. #}
	if(response === "")
	{
		refresh_calendar_and_sidebar();
		if (success_callback) success_callback()
	}
	else if (xml_http_request.status === 201)
	{
		{# reservation was created but there is some extra information to display #}
		$("#dialog .modal-content").html(response);
		$("#dialog").modal('show');
		refresh_calendar_and_sidebar();
		if (success_callback) success_callback()
	}
	else {# the response was non-empty so the tool requires configuration details before the reservation is created. #}
	{
		{# Construct the configuration dialog that is contained in the server response. #}
		$("#dialog .modal-content").html(response);
		$("#dialog").one('hidden.bs.modal', function() { return submit_event_with_more_information(ajax_post, success_callback) });
		$("#dialog").modal('show');
	}
}

{# This function is a callback for when reservation creation fails. #}
{# It removes the visual indication of the reservation (on the calendar) #}
{# and refreshes it with current events. #}
function unselect_and_refresh()
{
	$("#calendar").fullCalendar("unselect");
	refresh_calendar_and_sidebar();
}

function submit_event_with_more_information(ajax_post, success_callback)
{
	if($('#dialog_cancelled').val() === "true")
		return;
	serialize("#additional_event_parameters", ajax_post.data);
	jQuery.ajax(ajax_post)
		.fail(ajax_failure_callback("Oops, something went wrong!"))
		.done(function(response, status, xml_http_request)
		{
			return event_creation_success_callback(response, status, xml_http_request, ajax_post, success_callback)
		});
}

function event_render(event, element)
{
	if ('tooltip' in event)
		element.attr('title', event.tooltip)
	else if ('title' in event)
		element.attr('title', event.title)
}

function event_after_all_render()
{
	{# Remove visible tooltips first otherwise they get stuck #}
	$('.tooltip').remove()
	{# Show tooltips for events #}
	$('a.fc-time-grid-event').tooltip({ container: 'body', delay: { "show": 1000, "hide": 100 }})
}

{# This function is called when the user clicks and drags on the calendar to create a reservation. #}
function create(start, end, jsEvent, view)
{
	{# Find out which tool/area is selected in the item tree. #}
	let item = $(".selected");
	{# Only allow reservations to be created when a item has been selected. #}
	let item_selected = (item != null);
	{# Only allow selection to proceed when we're in reservation view (instead of usage view). #}
	let reservation_view = get_event_type() === 'reservations';
	{# Users may not create reservations when viewing their personal schedule. #}
	let personal_schedule = item.hasClass('personal_schedule');
	let all_tools = item.hasClass('all_tools');
	let all_areas = item.hasClass('all_areas');
	let all_areastools = item.hasClass('all_areastools');
	if(!item_selected || !reservation_view || personal_schedule || all_tools || all_areas || all_areastools)
	{
		$("#calendar").fullCalendar("unselect");
		return;
	}
	let event_properties =
	{
		"start": start.unix(),
		"end": end.unix(),
		"item_type": item.data('item-type'),
		"item_id": item.data('item-id'),
		"csrfmiddlewaretoken": "{{ csrf_token }}"
	};
	{# If the user is trying to create a scheduled outage, then put that in the event_properties. #}
	{# Otherwise, create a reservation (which is the normal case). #}
	let url;
	if($('.fc-scheduledOutage-button').html() === "I've finished creating scheduled outages")
	{
		url = "{% url 'create_outage' %}";
	}
	else
	{
		url = "{% url 'create_reservation' %}";
		let impersonate = $("#impersonate").val();
		if(impersonate)
			event_properties['impersonate'] = impersonate;
	}
	let post_data =
	{
		"url": url,
		"data": event_properties,
		"type": "POST",
		"dataType": "html"
	};
	ajax_post(url, event_properties, function(response, status, xml_http_request) { return event_creation_success_callback(response, status, xml_http_request, post_data) }, [unselect_and_refresh, ajax_failure_callback("Oops! Something went wrong")])
}

{# This function is called when the user clicks and drags on the calendar to resize a reservation. #}
function resize(event, delta, revertFunc, jsEvent, ui, view)
{
	let pieces = event.id.split(" ");
	let type = pieces[0];
	let id = pieces[1];
	let event_changes =
	{
		"id": id,
		"delta": delta.asMinutes(),
		"csrfmiddlewaretoken": "{{ csrf_token }}"
	};
	if(type === "Reservation")
	{
		let url = "{% url 'resize_reservation' %}"
		let post_data =
		{
			"url": url,
			"data": event_changes,
			"type": "POST",
			"dataType": "html"
		};
		ajax_post(url, event_changes, function(response, status, xml_http_request){return event_creation_success_callback(response, status, xml_http_request, post_data)}, [revertFunc, ajax_failure_callback("Reservation resize failed")], refresh_calendar_and_sidebar);
	}
	else if(type === "Outage")
	{
		ajax_post("{% url 'resize_outage' %}", event_changes, undefined, [revertFunc, ajax_failure_callback("Outage resize failed")], refresh_calendar_and_sidebar);
	}
}

{# This function is called when the user clicks and drags an event in order to move their reservation. #}
function move(event, delta, revertFunc, jsEvent, ui, view)
{
	let pieces = event.id.split(" ");
	let type = pieces[0];
	let id = pieces[1];
	let event_changes =
	{
		"id": id,
		"delta": delta.asMinutes(),
		"csrfmiddlewaretoken": "{{ csrf_token }}"
	};
	if(type === "Reservation")
	{
		let url = "{% url 'move_reservation' %}"
		let post_data =
		{
			"url": url,
			"data": event_changes,
			"type": "POST",
			"dataType": "html"
		};
		ajax_post(url, event_changes, function(response, status, xml_http_request) { return event_creation_success_callback(response, status, xml_http_request, post_data) }, [revertFunc, ajax_failure_callback("Reservation move failed")], refresh_calendar_and_sidebar)
	}
	else if(type === "Outage")
	{
		ajax_post("{% url 'move_outage' %}", event_changes, undefined, [revertFunc, ajax_failure_callback("Outage move failed")], refresh_calendar_and_sidebar);
	}
}

function details(event, jsEvent, view)
{
	let failure_dialog = ajax_failure_callback("Unable to display details");
	ajax_get(event.details_url, undefined, ajax_success_callback, [failure_dialog, refresh_calendar_and_sidebar]);
}

function cancel_reservation(url, reservation_id, reason)
{
	let failure_dialog = ajax_failure_callback("Unable to cancel this reservation");
	function reservation_cancel_success_callback()
	{
		$("#calendar").fullCalendar("removeEvents", reservation_id);
	}
	let contents = undefined;
	if(reason)
	{
		contents = {'reason': reason};
	}
	ajax_post(url, contents, reservation_cancel_success_callback, [failure_dialog, refresh_calendar_and_sidebar]);
}

function cancel_outage(url, outage_id)
{
	let failure_dialog = ajax_failure_callback("Unable to cancel this outage");
	function outage_cancel_success_callback()
	{
		$("#calendar").fullCalendar("removeEvents", outage_id);
		refresh_sidebar_icons();
	}
	ajax_post(url, undefined, outage_cancel_success_callback, [failure_dialog, refresh_calendar_and_sidebar]);
}

function set_reservation_title(url, reservation_id, title)
{
	let failure_dialog = ajax_failure_callback("Unable to set reservation title");
	ajax_post(url, {'title': title}, refresh_calendar_and_sidebar, [failure_dialog, refresh_calendar_and_sidebar]);
}

function change_reservation_project(url, project_id)
{
	let failure_dialog = ajax_failure_callback("Unable to change reservation project");
	ajax_post(url, {'project_id': project_id}, refresh_calendar_and_sidebar, [failure_dialog, refresh_calendar_and_sidebar]);
}

function on_browser_resize()
{
	$('#calendar').fullCalendar('option', 'height', $("#calendar").height());
}

function create_calendar()
{
	{# Documentation for properties: http://arshaw.com/fullcalendar/docs/ #}
	let calendar_properties =
	{
		"header":
		{
			left: "prev,next today{% if user.is_staff %} proxyReservation scheduledOutage{% endif %} login logout",
			center: "title",
			right: "agendaDay,agendaWeek,month"
		},
		"views": {
			"day": {
				"titleFormat": ' ',
				"columnFormat": '{{ calendar_day_column_format }}'
			},
			"week": {
				"titleFormat": ' ',
				"columnFormat": '{{ calendar_week_column_format }}'
			},
			"month": {
				"titleFormat": 'MMMM YYYY',
				"columnFormat": '{{ calendar_month_column_format }}'
			}
		},
		"firstDay": '{{ calendar_first_day_of_week }}',
		"scrollTime": '{{ calendar_start_of_the_day }}',
		"defaultView": '{{ calendar_view }}',
		"nowIndicator": '{{ calendar_now_indicator }}',
		"allDaySlot": false,
		"allDayDefault": false,
		"slotDuration": '00:15:00', {# 15 minutes each row #}
		"slotLabelInterval": '1:00', {# One hour intervals for label #}
		"editable": false,
		"selectable": true,
		"selectHelper": true,
		"select": create,
		"eventResize": resize,
		"eventRender": event_render,
		"eventAfterAllRender": event_after_all_render,
		"eventDrop": move,
		"eventClick": details,
		"height": $("#calendar").height(),
		"handleWindowResize": true,
		"windowResize": on_browser_resize,
		"slotEventOverlap": false,
		"buttonText": {
			"today": "Today",
			"day": "Day",
			"week": "Week",
			"month": "Month"
		},
		"customButtons": {
			"proxyReservation": {
				"text": "Reserve for someone else",
				"click": reserve_for_someone_else
			},
			"scheduledOutage": {
				"text": "Schedule an outage",
				"click": scheduled_outage
			},
			"login": {
				"text": "Login",
				"click": login_to_area
			},
			"logout": {
				"text": "Logout",
				"click": logout_of_area
			}
		}
	};
	$("#calendar").fullCalendar(calendar_properties);
}

function reserve_for_someone_else()
{
	let proxy_reservation_button = $(".fc-proxyReservation-button")[0];
	if($(proxy_reservation_button).html() === "Reserve for someone else")
	{
		ajax_get('{% url 'proxy_reservation' %}', undefined, reserve_for_someone_else_callback);
	}
	else
	{
		$(proxy_reservation_button).blur().html("Reserve for someone else");
		$("#impersonate").val('');
		$($(".fc-scheduledOutage-button")[0]).show();
	}
}

function reserve_for_someone_else_callback(response, status, xml_http_request)
{
	$("#dialog .modal-content").html(response);
	$("#dialog").modal('show');
}

function login_to_area()
{
	let item = get_selected_item();
	if (item && item !== "personal_schedule" && item !== "all_tools" && item !== "all_areas" && item !== "all_areastools")
	{
		item = JSON.parse(item)
		let event_changes =
		{
			"area": item.id,
		{% if user.active_project_count == 1 %}
			"project": "{{ user.active_projects.0.id }}",
		{% endif %}
			"csrfmiddlewaretoken": "{{ csrf_token }}"
		};
		let url = "{% url 'calendar_self_log_in' %}"
		let post_data =
		{
			"url": url,
			"data": event_changes,
			"type": "POST",
			"dataType": "html"
		};
		let callback = function() {
			logged_in = item.element_name;
			refresh_calendar_login();
		}
		ajax_post(url, event_changes, function(response, status, xml_http_request) { return event_creation_success_callback(response, status, xml_http_request, post_data, callback) }, [ajax_failure_callback("Login to area failed")], refresh_sidebar_area_icons)
	}
}

function logout_of_area()
{
	ajax_get("{% url 'self_log_out' user.id %}", null, function () {
		logged_in = false;
		refresh_calendar_login();
	}, ajax_failure_callback("Logout of area failed"), refresh_calendar_and_sidebar_area_icons)
}

function scheduled_outage()
{
	let scheduled_outage_button = $(".fc-scheduledOutage-button")[0];
	let proxy_reservation_button = $(".fc-proxyReservation-button")[0];
	if($(scheduled_outage_button).html() === "Schedule an outage")
	{
		$(proxy_reservation_button).hide();
		$(scheduled_outage_button).blur().html("I've finished creating scheduled outages");
	}
	else
	{
		$(proxy_reservation_button).show();
		$(scheduled_outage_button).blur().html("Schedule an outage");
	}
}

function refresh_sidebar_icons()
{
	$.getScript('{% url 'refresh_sidebar_icons' %}')
}

function refresh_sidebar_area_icons()
{
	$.getScript('{% url 'refresh_sidebar_icons' item_type='area' %}')
}

function refresh_calendar_and_sidebar()
{
	$("#calendar").fullCalendar('refetchEvents');
	refresh_sidebar_icons()
}

function refresh_calendar_login()
{
	let login_button = $(".fc-login-button")[0];
	let logout_button = $(".fc-logout-button")[0];
	$(login_button).hide()
	$(logout_button).hide();
	{# Login and logout are only available on reservations events and when personal_schedule isn't selected #}
	let item = get_selected_item();
	let event_type = get_event_type();
	if (event_type === 'reservations' && item !== 'personal_schedule' && item !== 'all_tools' && item !== "all_areas" && item !== "all_areastools")
	{
		if (logged_in)
		{
			{% if self_logout %}
				$(logout_button).html("Logout of the " + logged_in)
				$(logout_button).show()
			{% endif %}
		}
		else
		{
			{% if self_login %}
			item = JSON.parse(item);
			if (item.type === 'area')
			{
				$(login_button).html("Login to the "+item.element_name);
				$(login_button).show();
			}
			{% endif %}
		}
	}
}

function refresh_calendar_and_sidebar_area_icons()
{
	$("#calendar").fullCalendar('refetchEvents');
	refresh_sidebar_area_icons()
}

function change_calendar_event_type(calling_element)
{
	set_event_type(calling_element.text);
	let expand_collapse = $("#expand-collapse").hide();
	let item_search = $("#item_search").hide();
	let item_tree = $(".item_tree, .item_tree_fieldset").hide();
	let event_type = get_event_type();
	let extra_links = $("#extra-links");
	let user_search = $("#user_search").hide();
	let chosen_user_button = $("#chosen_user_button").show();
	let proxy_reservation_button = $(".fc-proxyReservation-button")[0];
	let scheduled_outage_button = $(".fc-scheduledOutage-button")[0];
	if(event_type === "reservations")
	{
		user_search.hide();
		chosen_user_button.hide();
		extra_links.show();
		expand_collapse.show();
		item_search.show();
		item_tree.show();
		$(proxy_reservation_button).show();
		$(scheduled_outage_button).show();
		update_event_sources();
	}
	else if(event_type === "{{ facility_name|lower }} usage")
	{
		user_search.hide();
		chosen_user_button.hide();
		extra_links.show();
		expand_collapse.show();
		item_search.show();
		item_tree.show();
		$(proxy_reservation_button).hide();
		$(scheduled_outage_button).hide();
		update_event_sources();
	}
	else if(event_type === "specific user")
	{
		user_search.show();
		chosen_user_button.show();
		extra_links.hide();
		expand_collapse.hide();
		item_search.hide();
		item_tree.hide();
		$(proxy_reservation_button).hide();
		$(scheduled_outage_button).hide();
		clear_specific_user();
	}
}

function get_specific_user_activity(jquery_event, search_selection, dataset_name)
{
	$("#user_search").typeahead('val', search_selection.id).hide();
	$("#chosen_user_button").text(search_selection.name).show();
	update_event_sources();
}

function clear_specific_user()
{
	$("#chosen_user_button").hide();
	$("#user_search").typeahead('val', '').show().focus();
	update_event_sources();
}

function on_load()
{
    $("html").css("overflow", "hidden");
	create_calendar();
	set_interval_when_visible(document, refresh_calendar_and_sidebar, 30000);
	set_item_link_callback(update_event_sources);
	enable_item_tree_toggling();
	$('#item_search').autocomplete('items', on_item_search_selection, {% json_search_base_with_extra_fields tools|add:areas %}, {% if tools and areas %}false{% else %}true{% endif %});
	$("#item_search").focus();
	load_sidebar_state();
	$(".item_tree").show(); {# Item tree is initially hidden so that previous expand/collapse state of categories is configured before it's visible. #}
	{% if auto_select_item_id %}
		expand_to_item({{ auto_select_item_id }}, {{ auto_select_item_type }});
	{% else %}
		update_event_sources();
	{% endif %}
	{% if user.is_staff %}
		$("#user_search").autocomplete('users', get_specific_user_activity, {{ users|json_search_base }});
	{% endif %}
	$('[data-toggle~="tooltip"]').tooltip({ container: 'body' });
	refresh_calendar_login();
}

$(on_load);

</script>

{% endblock %}
