// ----------------------------------------------------
// ------ jquery.pestDashboard ------------------------
// ----------------------------------------------------
// Controls the pest dashboard
// ----------------------------------------------------

; (function ($, window, document, undefined) {

	var pluginName = "pestDashboard";

	function pestDashboard(options) {
		this._name = pluginName;
		this._defaults = $.fn.pestDashboard.defaults;
		this.options = $.extend({}, this._defaults, options);

		this.init();
	};

	function setTime() {
		var now = new Date,
			hours = now.getHours() % 12 || 12,
			ampm = now.getHours() < 12 ? " AM" : " PM",
			minutes = now.getMinutes(),
			timeStr = [hours, (minutes < 10 ? "0" + minutes : minutes)].join(":") + ampm;

		$("#currentTime").html(timeStr);

		// every minute
		setTimeout(setTime, 60000);
	};

	function autoReload() {

		if ($("#currentTime").is(":visible")) {
			$("#hreloadBtn").click();
		}

		setTimeout(autoReload, 60000);
	}

	function htmlEncode(value) {
		return $("<div/>").text(value).html();
	}

	function htmlDecode(value) {
		return $("<div/>").html(value).text();
	}

	function isNullOrUndefined(variable) {

		if (typeof variable === "undefined" || variable === null) {
			return true;
		}

		return false;
	}

	function isNullOrWhiteSpace(str) {
		if (typeof str === "undefined" ||
			!str ||
			str.length === 0 ||
			!/[^\s]/.test(str) ||
			/^\s*$/.test(str) ||
			str.replace(/\s/g, "") === "") {
			return true;
		} else {
			return false;
		}
	}

	$.extend(pestDashboard.prototype, {

		init: function () {
			this.buildCache();

			this.bindEvents();

			this.currentView = "schedule";

			this.DashboardData = null;

			this.initDatePicker();

			setTime();

			this.date = this.options.date;

			this.table = null;

			this.selectedTable = null;

			this.assignTechniciansTable = null;

			this.fsm = false;

			this.vectorLayer = null;
			this.vectorSource = null;

			this.techLocationVectorLayer = null;
			this.techLocationVectorSource = null;
			this.techSelectedOnMap = null;
			this.techSelectedOnMapCheckInTime = null;
			this.techSelectedOnMapCheckOutTime = null;
			this.techSelectedUserId = null;
			this.techLocationVectorSourceUserId = null;

			this.alertLocationVectorLayer = null;
			this.alertLocationVectorSource = null;
			this.alertSelectedOnMapTech = null;
			this.alertSelectedOnMapAddress = null;
			this.alertSelectedAppointmentId = null;
			this.alertLocationVectorSourceAppointmentId = null;

			this.selectClick = null;

			var today = new Date();

			this.dateQueryString = "";

			this.setDate(today);

			this.allowableStatusValues = [];

			this.allowableDiaries = [];

			this.registerSearch = "";
			this.scheduleSearch = "";

			this.refreshView();

			this.setupTechicianTable();

			setTimeout(autoReload, 60000);
		},

		destroy: function () {
			this.unbindEvents();
		},

		buildCache: function () {

			var plugin = this;

			plugin.$body = $("body");
			plugin.$menuItems = $(plugin.options.menuItemSelector);
			plugin.$errorAlertModal = $(plugin.options.errorAlertElementId);
			plugin.$logoBtn = $(plugin.options.logoElementId);

			plugin.$statusWaiting = $(plugin.options.statusWaitingElementId + " span.row span.column span.statNum span.stringValueStat");
			plugin.$statusComplete = $(plugin.options.statusCompleteElementId + " span.row span.column span.statNum span.stringValueStat");
			plugin.$statusStarted = $(plugin.options.statusStartedElementId + " span.row span.column span.statNum span.stringValueStat");
			plugin.$statusNoAccess = $(plugin.options.statusNoAccessElementId + " span.row span.column span.statNum span.stringValueStat");
			plugin.$statusUnassigned = $(plugin.options.statusUnassignedElementId + " span.row span.column span.statNum span.stringValueStat");
			plugin.$statusCancelled = $(plugin.options.statusCancelledElementId + " span.row span.column span.statNum span.stringValueStat");
			plugin.$statusStopped = $(plugin.options.statusStopElementId + " span.row span.column span.statNum span.stringValueStat");
			plugin.$statusCovid = $(plugin.options.statusCovidElementId + " span.row span.column span.statNum span.stringValueStat");
			plugin.$statusAlert = $(plugin.options.statusAlertElementId + " span.row span.column span.statNum span.stringValueStat");

			plugin.$statusLoading = $("button.statBlock span.row span.column span.statNum span.statusLoading");
			plugin.$statusValues = $("button.statBlock span.row span.column span.statNum span.stringValueStat");

			plugin.$loadingPanel = $(plugin.options.loaderPanelId);

			plugin.$statusButtons = $(plugin.options.statusButtonsSelector);
			plugin.$diaryButtons = $(plugin.options.diaryButtonsSelector);

			plugin.$periodButtons = $(plugin.options.periodButtonsSelector);

			plugin.$allDiariesButton = $(plugin.options.allButtonElementId);

			plugin.$reloadButton = $(plugin.options.reloadButtonElementId);

			plugin.$autoReloadButton = $(plugin.options.autoReloadButtonElementId);

			plugin.$appointmentTable = $(plugin.options.appointmentTableElementId);
			plugin.$registerTable = $(plugin.options.registerTableElementId);

			plugin.$selectedAppointmentTable = $(plugin.options.selectedAppointmentTableElementId);
			plugin.$assignmentTable = $(plugin.options.selectedTechnicianTableElementId);

			plugin.$cancelSelectionPanelBtn = $(plugin.options.cancelSelectionPanelCloseElementId);
			plugin.$cancelSelectionBtn = $(plugin.options.cancelSelectionBtnElementId);

			plugin.$assignSelectedBtn = $(plugin.options.assignSelectedBtnElementId);

			plugin.$assignTechBtn = $(plugin.options.assignTechBtnElementId);

			plugin.$periodFilter = $(plugin.options.periodFilterContainerId);

			console.log("apt: " + plugin.$appointmentTable.length);

			console.log("cols: " + $(plugin.options.appointmentTableElementId + " thead tr th").length);

			plugin.$selectedAppointmentTable = $(plugin.options.selectedAppointmentTableElementId);
			plugin.$selectedRegisterTable = $(plugin.options.selectedRegisterTableElementId);

		},

		setAllowableStatusArray: function() {

			var plugin = this;

			var $active = $(plugin.options.activeStatusButtonsSelector);

			var d = [];

			$.each($active, function(idx, val) {

				var s = $(val).data("filter");

				d.push(s);

			});

			plugin.allowableStatusValues = d;
		},

		setAllowableDiaryArray: function () {

			var plugin = this;

			var $active = $(plugin.options.activeDiaryButtonsSelector);

			var d = [];

			$.each($active, function (idx, val) {

				var s = $(val).attr("value");

				d.push(s);

			});

			plugin.allowableDiaries = d;
		},

		filterData: function() {

			var plugin = this;

			if (plugin.currentView !== "schedule") {
				return;
			}

			var periodFilter = $(plugin.options.periodButtonsSelector + ".active").data("filter");

			console.log("Raw period: " + $(".periodBtn.active").data("filter"));

			console.log('Period count: ' + $(".periodBtn.active").length);

			console.log("period: " + periodFilter);

			plugin.table.columns(6).search(periodFilter, false, false, true);

			if (plugin.$allDiariesButton.is(":checked") || plugin.allowableDiaries.length === 0) {
				plugin.table.columns(1).search("");

				console.log("no diary filter");
			} else {
				var diaryValues = plugin.allowableDiaries.join("|");

				console.log("Diaries: " + diaryValues);

				plugin.table.columns(1).search(diaryValues, true, false, true);
			}

			if (plugin.$statusButtons.not(".active")) {
				var statusValues = plugin.allowableStatusValues.join("|");

				console.log("StatusValues: " + statusValues);

				plugin.table.columns(5).search(statusValues, true, false, true);
			} else {
				plugin.table.columns(5).search("");
			}

			plugin.table.draw();
		},

		setDate: function(dt) {

			var plugin = this;

			plugin.date = dt;

			var today = new Date();

			if (plugin.date.setHours(0, 0, 0, 0) !== today.setHours(0, 0, 0, 0)) {
				$("#currentTime").hide();
			} else {
				$("#currentTime").show();
			}

			plugin.reloadData(true);

			if (plugin.assignTechniciansTable != null) {
				plugin.assignTechniciansTable.ajax.reload(null, false);
			}
		},

		initDatePicker: function() {

			var plugin = this;

			$('input[name="datefilter"]').daterangepicker({
					"singleDatePicker": true,
					"autoApply": true,
					"showDropdowns": true,
					ranges: {
						'Today': [moment(), moment()],
						'Yesterday': [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
						'Last 7 Days': [moment().subtract(6, 'days'), moment()],
						'Last 30 Days': [moment().subtract(29, 'days'), moment()],
						'This Month': [moment().startOf('month'), moment().endOf('month')],
						'Last Month': [
							moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')
						]
					},
					"locale": {
						"format": "ddd DD MMM",
						"separator": " - ",
						"applyLabel": "Apply",
						"cancelLabel": "Cancel",
						"fromLabel": "From",
						"toLabel": "To",
						"customRangeLabel": "Custom",
						"weekLabel": "W",
						"daysOfWeek": [
							"Su",
							"Mo",
							"Tu",
							"We",
							"Th",
							"Fr",
							"Sa"
						],
						"monthNames": [
							"January",
							"February",
							"March",
							"April",
							"May",
							"June",
							"July",
							"August",
							"September",
							"October",
							"November",
							"December"
						],
						"firstDay": 1
					},
					"startDate": plugin.options.startDate,
					//"endDate": plugin.options.endDate,
					//"minDate": plugin.options.minDate,
					//"maxDate": plugin.options.maxDate,
					"opens": "right"
				},
				function(start, end, label) {
					console.log('New date range selected: ' +
						start.format('dddd DD/MM/YYYY') +
						' to ' +
						end.format('dddd DD/MM/YYYY') +
						' (predefined range: ' +
						label +
						')');

					plugin.dateQueryString = start.format("YYYY-MM-DD");

					plugin.setDate(start._d);
				});

		},

		reloadData: function(showLoader) {

			var plugin = this;

			var url = plugin.options.dataRefreshUrl;

			var today = new Date();

			if (plugin.date.setHours(0, 0, 0, 0) !== today.setHours(0, 0, 0, 0)) {
				url += "?date=" + plugin.dateQueryString;
			}

			if (showLoader === true) {
				plugin.$loadingPanel.foundation("open");
			}

			plugin.$statusValues.hide();
			plugin.$statusLoading.show().attr("aria-hidden", "false");

			$.getJSON(url, function (data) {

				//console.log(data);

				plugin.DashboardData = data;

				plugin.setStatusCounts(data.Counts);

				plugin.refreshView();

				if (showLoader) {
					plugin.$loadingPanel.foundation("close");
				}

				console.log(plugin.$statusValues.length + " values");

				plugin.$statusValues.fadeIn();
				plugin.$statusLoading.hide().attr("aria-hidden", "true");
			});
		},

		bindEvents: function () {
			var plugin = this;

			plugin.$menuItems.on("click", function (e) {
				e.preventDefault();

				var $this = $(this);

				plugin.changeMenu($this);
			});

			plugin.$logoBtn.on("click", function (e){
				e.preventDefault();

				var $this = $(this);

				if (plugin.fsm === false) {
					plugin.fullScreen();
				} else {
					plugin.normalScreen();
				}

			});

			plugin.$statusButtons.on("click", function (e) {

				if (plugin.currentView !== "schedule") {
					return;
				}

				var $this = $(this);

				$(this).toggleClass("active");

				plugin.setAllowableStatusArray();

				plugin.filterData();
			});

			plugin.$diaryButtons.on("click", function (e) {

				if (plugin.currentView !== "schedule") {
					return;
				}

				var $this = $(this);

				if (plugin.$diaryButtons.not(":checked").length) {
					plugin.$allDiariesButton.prop("checked", false);
				}
				else {
					plugin.$allDiariesButton.prop("checked", true);
				}

				plugin.setAllowableDiaryArray();

				plugin.filterData();
			});

			plugin.$periodButtons.on("click", function (e) {

				if (plugin.currentView !== "schedule") {
					return;
				}

				var $this = $(this);

				plugin.$periodButtons.removeClass("active");

				$this.addClass("active");

				plugin.filterData();
			});

			plugin.$allDiariesButton.on("change", function () {

				if (plugin.currentView !== "schedule") {
					return;
				}

				if (plugin.$allDiariesButton.is(":checked")) {
					plugin.$diaryButtons.prop("checked", true);
				}
				else {
					plugin.$diaryButtons.prop("checked", false);
				}

				plugin.setAllowableDiaryArray();

				plugin.filterData();

			});

			plugin.$reloadButton.on("click", function (e) {

				var $this = $(this);

				plugin.reloadData(true);

			});

			plugin.$autoReloadButton.on("click", function (e) {

				var $this = $(this);

				plugin.reloadData(false);

			});

			plugin.$cancelSelectionPanelBtn.on("click", function (e) {
				var $this = $(this);

				plugin.cancelSelectionPanel();
			});

			plugin.$cancelSelectionBtn.on("click", function (e) {
				var $this = $(this);

				plugin.cancelSelectionPanel();
			});

			plugin.$assignSelectedBtn.on("click", function (e) {
				var $this = $(this);

				plugin.showTechicianSelection();
			});

			plugin.$assignTechBtn.on("click", function (e) {
				var $this = $(this);

				plugin.assignAppointments();
			});

			// in the unlikely event of window resize
			var windowResizeDelay;

			$(window).on("resize", function (e) {
				clearTimeout(windowResizeDelay);
				windowResizeDelay = setTimeout(function () {

					if (plugin.table !== null) {
						plugin.table.destroy();
						plugin.table = null;
					}

					plugin.refreshView();

				}, 300);
			});

		},

		unbindEvents: function () {
			var plugin = this;

			plugin.$menuItems.off("click");

		},

		fullScreen: function() {

			var plugin = this;

			plugin.fsm = true;

			$("#tableColumn").removeClass("large-5");
			$("#tableColumn").hide();

			$("#mapColumn").removeClass("large-7");
			$("#mapColumn").addClass("small-12");

			if (plugin.options.map !== null) {
				plugin.options.map.updateSize();
			}

		},

		normalScreen: function() {

			var plugin = this;

			plugin.fsm = false;

			$("#tableColumn").addClass("large-5");
			$("#tableColumn").show();

			$("#mapColumn").removeClass("small-12");
			$("#mapColumn").addClass("large-7");

			if (plugin.options.map !== null) {
				plugin.options.map.updateSize();
			}

		},

		showError: function (title, errorMessage) {
			var plugin = this;

			plugin.$errorMessageContainer.html('<p class="lead">' + errorMessage + "</p>");

			var popup = new Foundation.Reveal($errorAlertModal);
			popup.open();

		},

		save: function (id, remove, successFnc) {

			var plugin = this;

			plugin.clearError();

			if (plugin.options.entriesUpdateUrl == null) {
				plugin.setError("No save url has been set");
				return;
			}

			var saveData = {
				Id: id,
				Remove: remove
			};

			$.ajax({
				type: "POST",
				url: plugin.options.entriesUpdateUrl,
				data: JSON.stringify(saveData),
				dataType: "json",
				contentType: "application/json; charset=utf-8",
				cache: false,
				success: function (data) {
					if (data == null) {
						plugin.setError("An error has occurred during the save.");
						return;
					}

					successFnc();
				},
				error: function (jqXHR, textStatus, errorThrown) {
					plugin.setError("A problem prevented the changes from being saved: " + textStatus);
				},
				complete: function () {

				}
			});
		},

		changeMenu: function($menuItem) {

			var plugin = this;

			plugin.$menuItems.removeClass("active");

			$menuItem.addClass("active");

			var dataSet = $menuItem.data("dataset");

			if (dataSet === "schedule") {

				if (plugin.currentView === "schedule") {
					return;
				}

				plugin.setScheduleView(true);

			} else if (dataSet === "register") {

				if (plugin.currentView === "register") {
					return;
				}

				plugin.setRegisterView(true);

			}

		},

		changeView: function() {

			var plugin = this;

			plugin.showError("Testing error modal", "This is a drill please ignore");

		},

		refreshView: function() {

			var plugin = this;

			if (plugin.currentView === "schedule") {
				plugin.setScheduleView((plugin.table !== null));
			} else {
				plugin.setRegisterView((plugin.table !== null));
			}

		},

		filterAppointmentMarkers: function(ids) {

			var plugin = this;

			if (plugin.vectorSource === null) {
				return;
			}

			var features = plugin.vectorSource.getFeatures();

			$.each(features, function (idx, f) {

				var appointmentId = f.get("appointmentId");

				if (ids.includes(appointmentId)) {

					var pinSrc = f.get("pin");

					var iconStyle = new ol.style.Style({

						image: new ol.style.Icon(({
							anchorOrigin: "top-left",
							src: pinSrc
						}))
					});

					f.setStyle(iconStyle);

				} else {

					f.setStyle(new ol.style.Style(null));
				}

			});

		},

		filterUserMarkers: function(ids) {

			var plugin = this;

			if (plugin.vectorSource === null) {
				return;
			}

			var features = plugin.vectorSource.getFeatures();

			$.each(features, function (idx, f) {

				var userId = f.get("userId");

				if (ids.includes(userId)) {

					var pinSrc = f.get("pin");

					var iconStyle = new ol.style.Style({

						image: new ol.style.Icon(({
							anchorOrigin: "top-left",
							src: pinSrc
						}))
					});

					f.setStyle(iconStyle);

				} else {

					f.setStyle(new ol.style.Style(null));
				}

			});

		},

		refreshScheduleView: function() {

			var plugin = this;

			var data = null;

			if (plugin.DashboardData != null) {
				data = plugin.DashboardData.Appointments;
			}

			plugin.table.data = data;

			plugin.table.draw();
		},

		refreshRegisterView: function () {

			var plugin = this;

			var data = null;

			if (plugin.DashboardData != null) {
				data = plugin.DashboardData.Technicians;
			}

			plugin.table.data = data;
			plugin.table.draw();
		},

		setScheduleView: function(reload) {

			var plugin = this;

			if (plugin.table !== null) {
				plugin.table.destroy();
			}

			plugin.$registerTable.hide();
			plugin.$periodFilter.show();
			plugin.$appointmentTable.show();

			plugin.currentView = "schedule";

			$("body").removeClass("registerLayout");

			$("body").addClass("schedulerLayout");

			var contentAreaHeight = $("#article").outerHeight() - 125;

			$("div.diaryHeader").show();

			var data = null;

			if (plugin.DashboardData != null) {
				data = plugin.DashboardData.Appointments;
			}

			plugin.table = plugin.$appointmentTable.DataTable({
				"sDom": "t",
				"rowId": "AppointmentId",
				"dom": '<"toolbar">frtip',
				"retrieve": true,
				"paging": false,
				"ordering": true,
				"info": false,
				"scrollY": contentAreaHeight,
				"scrollX": true,
				"scrollCollapse": true,
				columns: [
					{ data: "Address", defaultContent: "" },
					{ data: "Diary", defaultContent: "" },
					{ data: "Slots", className: "text-center", defaultContent: "" },
					{ data: "ReportId", visible: false, defaultContent: "" },
					{ data: "Technician", defaultContent: "" },
					{ data: "StatusHtml", defaultContent: "" },
					{ data: "TimePeriod", className: "text-center", defaultContent: "" }
				],
				select: {
					style: "single"
				},
				data: data
			});

			plugin.table.on("select", function (e, dt, type, indexes) {
				if (type === "row") {
					var rows = plugin.table.rows(indexes).nodes().to$();
					$.each(rows, function () {
						if ($(this).hasClass('noSelect'))
							plugin.table.row($(this)).deselect();
					});
				}
			});

			plugin.table.on("select", function (e, dt, type, indexes) {
				if (type === "row") {
					var rows = plugin.table.rows(indexes).nodes().to$();
					$.each(rows, function () {
						if ($(this).hasClass("noSelect"))
							plugin.table.row($(this)).deselect();
					});
				}

				var appointmentRow = plugin.table.rows({ selected: true }).data();

				if (appointmentRow.length !== 1) {
					return;
				}

				var id = appointmentRow[0].AppointmentId;

				plugin.zoomToAppointment(id);
			});

			plugin.table.on("search.dt", function () {

				if (plugin.table === null) {
					return;
				}

				plugin.scheduleSearch = plugin.table.search();

				console.log("search is " + plugin.table.search());

				var appointments = plugin.table.rows({ search: "applied" }).data();

				var ids = [];

				$.each(appointments, function (i, item) {
					ids.push(item.AppointmentId);
				});

				plugin.filterAppointmentMarkers(ids);

			});

			$("div.toolbar").html("<p>Technicians Schedule</p>");
			$(".dataTables_filter input").attr("placeholder", "Type and search...");

			$(".scheduleTable tbody").on("click", "tr", function () {

				var trAlert = plugin.table.rows(".selected").data().length;

				//$(this).toggleClass('selected');

				console.log(trAlert + " row(s) selected");

				if ($(this).hasClass("selected")) {
					$(this).removeClass("selected");
				}
				else {
					plugin.table.$("tr.selected").removeClass("selected");
					$(this).addClass("selected");
				}

			});

			if (plugin.options.map == null) {
				return;
			}

			plugin.options.map.updateSize();

			if (plugin.vectorLayer != null) {
				plugin.options.map.removeLayer(plugin.vectorLayer);
			}

			if (plugin.techLocationVectorLayer != null) {
				plugin.options.map.removeLayer(plugin.techLocationVectorLayer);
				plugin.techLocationVectorLayer = null;
			}

			var vectorSource = new ol.source.Vector({
				features: []
			});

			var vectorLayer = new ol.layer.Vector({
				source: vectorSource
			});

			var alertLocationVectorSource = new ol.source.Vector({
				features: []
			});

			var alertLocationVectorLayer = new ol.layer.Vector({
				source: alertLocationVectorSource,
				name: 'AlertFiltered'
			});

			plugin.vectorLayer = vectorLayer;
			plugin.vectorSource = vectorSource;

			plugin.alertLocationVectorLayer = alertLocationVectorLayer;
			plugin.alertLocationVectorSource = alertLocationVectorSource;

			plugin.options.map.addLayer(plugin.vectorLayer);
			plugin.options.map.addLayer(plugin.alertLocationVectorLayer);

			var extent = new ol.extent.createEmpty();

			var markers = 0;

			$.each(data, function (key, val) {

				var easting = parseFloat(val.Easting);
				var northing = parseFloat(val.Northing);

				if (isNaN(easting) || isNaN(northing) || typeof val.PinSrc === "undefined") {
					return;
				}

				var reportedEasting = parseInt(val.ReportedEasting);
				var reportedNorthing = parseInt(val.ReportedNorthing);

				try {

					var newMarker = new ol.Feature({
						geometry: new ol.geom.Point([easting, northing]),
						appointmentId: val.AppointmentId,
						markerType: "appointmentMarker",
						address: val.PinTitle,
						addressHtml: val.Address,
						postcode: val.PostCode,
						technician: val.Technician.replace("<br>", " "),
						status: val.StatusText,
						diary: val.Diary,
						slots: val.Slots,
						reportId: val.ReportId,
						pests: val.Pests,
						timePeriod: val.TimePeriod,
						timeLabel: val.TimeLabel,
						viewLink: val.ViewLink,
						time: val.Time,
						alerts: val.FlagsHtml,
						reportedEasting: reportedEasting,
						reportedNorthing: reportedNorthing,
						pin: val.PinSrc
					});

					var newIconStyle = new ol.style.Style({

						image: new ol.style.Icon(({
							anchorOrigin: "top-left",
							src: val.PinSrc
						}))

					});

					newMarker.setStyle(newIconStyle);

					vectorSource.addFeature(newMarker);

					extent = new ol.extent.extend(extent, newMarker.getGeometry().getExtent());

					markers++;

				} catch (err) {
					console.log("Err: " + err);
				}

			});

			if (markers > 0 && reload === false) {
				plugin.options.map.getView().fit(extent);
			}

			//setTimeout(function () { plugin.zoomToAppointment(11431); }, 1000);

			if (plugin.options.mapPopupOverlay == null) {
				return;
			}

			if (plugin.options.selectClick != null) {
				plugin.options.map.removeInteraction(plugin.options.selectClick);
			}

			var content = document.getElementById('popup-content');

			var selectClick = new ol.interaction.Select({

			});

			plugin.options.selectClick = selectClick;

			plugin.options.map.addInteraction(selectClick);

			selectClick.on("select", function (e) {

				var features = e.target.getFeatures();

				if (features.getLength() < 1) {
					return;
				}

				var feature = features.getArray()[0];

				var coordinate = feature.getGeometry().getCoordinates();

				var markerType = feature.get("markerType");
				var html = '';

				if (markerType === "appointmentMarker") {

					var appointmentId = feature.get('appointmentId');
					var address = feature.get("address");
					var postcode = feature.get("postcode");
					var technician = feature.get("technician");
					var timePeriod = feature.get("timePeriod");
					var status = feature.get("status");
					var diary = feature.get("diary");
					var pests = feature.get("pests");
					var time = feature.get("time");
					var timeLabel = feature.get("timeLabel");
					var alerts = feature.get("alerts");
					var viewLink = feature.get("viewLink");

					var reportedEasting = feature.get("reportedEasting");
					var reportedNorthing = feature.get("reportedNorthing");

					html = '<p class="pinTitle">' + address + "</p>";

					if (isNullOrWhiteSpace(postcode) === false) {
						html += '<p class="pinPostcode">' + postcode + "</p>";
					}

					if (isNullOrWhiteSpace(technician) === false) {
						html += '<p class="row"><span class="columns small-6 labelVal">Technician</span><span class="columns small-6 valueVal">' + technician + "</span></p>";
					}

					if (isNullOrWhiteSpace(timePeriod) === false) {
						html += '<p class="row"><span class="columns small-6 labelVal">Period</span><span class="columns small-6 valueVal">' + timePeriod + "</span></p>";
					}

					if (isNullOrWhiteSpace(diary) === false) {
						html += '<p class="row"><span class="columns small-6 labelVal">Diary</span><span class="columns small-6 valueVal">' + diary + "</span></p>";
					}

					if (isNullOrWhiteSpace(pests) === false) {
						html += '<p class="row"><span class="columns small-6 labelVal">Pests</span><span class="columns small-6 valueVal">' + pests + "</span></p>";
					}

					if (isNullOrWhiteSpace(status) === false) {
						html += '<p class="row"><span class="columns small-6 labelVal">Status</span><span class="columns small-6 valueVal">' + status + "</span></p>";
					}

					if (isNullOrWhiteSpace(timeLabel) === false && isNullOrWhiteSpace(time) === false) {
						html += '<p class="row"><span class="columns small-6 labelVal">' + timeLabel + '</span><span class="columns small-6 valueVal">' + time + "</span></p>";
					}

					if (isNullOrWhiteSpace(alerts) === false) {
						html += '<p class="row"><span class="columns small-6 labelVal">Alerts</span><span class="columns small-6 valueVal">' + alerts + "</span></p>";
					}

					if (isNullOrWhiteSpace(viewLink) === false) {
						html += '<div class="row"><a href="' + viewLink + '" target="_blank" class="button rounded small expanded">Edit</a></div>';
					}

					plugin.alertSelectedOnMapTech = technician;
					plugin.alertSelectedOnMapAddress = address;
					plugin.alertSelectedAppointmentId = appointmentId;

					if (isNaN(reportedEasting) === false && isNaN(reportedNorthing) === false) {

						html += '<p class="row"><span class="columns small-6 labelVal">Reported From</span><span class="columns small-6 valueVal">' +
							' <img src="https://cdn.mapmarker.io/api/v1/fa/stack?size=120&amp;icon=fa-map-pin&amp;color=%23FFF000&amp;on=fa-circle&amp;oncolor=%23009CE&amp;hoffset=1&amp;voffset=0&amp;iconsize=50&amp;" alt="View on map" width="34" height="34" data-e="' + reportedEasting + '" data-n="' + reportedNorthing + '">' +
							"</span></p>";

						plugin.setReportedPosition(reportedEasting, reportedNorthing, technician, address, coordinate);
					}
					else {
						plugin.clearReportedLayer();
					}

					content.innerHTML = html;

				} else {
					var technician = feature.get("technician");
					var address = feature.get("address");

					html = '<p class="pinTitle">' + address + '</p><p class="row"><span class="columns small-6 labelVal">Technician</span><span class="columns small-6 valueVal">' + technician + '</span></p>';

					content.innerHTML = html;
				}

				plugin.options.mapPopupOverlay.setPosition(coordinate);

				features.clear();
			});

			if (isNullOrWhiteSpace(plugin.scheduleSearch) === false) {
				plugin.table.search(plugin.scheduleSearch);
			}

			plugin.setupMapFeatureSelection();

			plugin.filterData();
		},

		showAssignWaitingMessage: function () {

			var plugin = this;

			$("#selectedAppointmentsPanel").hide();
			$("#assignTechPanel").hide();
			$("#assignWarningPanel").hide();
			$("#assignWaitingPanel").show();

			plugin.$cancelSelectionBtn.hide();
			plugin.$assignSelectedBtn.hide();
			plugin.$assignTechBtn.hide();
			plugin.$assignSelectedBtn.attr("aria-expanded", "true").hide();

		},

		showAssignErrorMessage: function (title, message) {

			var plugin = this;

			$("#selectedAppointmentsPanel").hide();
			$("#assignTechPanel").hide();
			$("#assignWaitingPanel").hide();
			$("#assignWarningPanel").show();

			$("#serverErrorTitle").text(title);
			$("#serverErrorMessage").text(message);

			plugin.$assignSelectedBtn.hide();
			plugin.$cancelSelectionBtn.hide();
			plugin.$assignTechBtn.hide();
			plugin.$assignSelectedBtn.attr("aria-expanded", "true").hide();

		},

		setupSelectedAppointmentTable: function (data) {

			var plugin = this;

			if (plugin.selectedTable !== null) {
				plugin.selectedTable.clear().destroy();
				plugin.selectedTable = null;
			}

			$("#selectedAppointmentsPanel").show();
			$("#assignTechPanel").hide();
			$("#assignWarningPanel").hide();
			$("#assignWaitingPanel").hide();
			plugin.$assignSelectedBtn.show();
			plugin.$cancelSelectionPanelBtn.show();

			var contentAreaHeightOffCanvas = $('#article').outerHeight() - 230;

			plugin.selectedTable = plugin.$selectedAppointmentTable.DataTable({
				"rowId": "AppointmentId",
				searching: false,
				retrieve: true,
				paging: false,
				ordering: true,
				info: true,
				scrollY: contentAreaHeightOffCanvas,
				scrollX: true,
				scrollCollapse: true,
				select: {
					style: 'multi'
				},
				language: {
					emptyTable: "<div class='callout warning rounded text-center'><p class'h4'>No data selected</p></div>",
					sZeroRecords: "<div class='callout warning rounded text-center'><p class'h4'>No matching jobs selected</p></div>",
					sInfo: "_TOTAL_ jobs",
					select: {
						rows: {
							_: "%d jobs selected to assign",
							0: "Click jobs to edit your selection",
							1: "1 job selected to assign"
						}
					}
				},
				dom: '<"topInfo columns large-10"i><"toolbarFeatures columns large-2">rt<"bottom"flp>',
				columns: [
					{ data: "Address", defaultContent: "" },
					{ data: "TimePeriod", className: "text-center", defaultContent: "" },
					{ data: "Diary", defaultContent: "" },
					{ data: "Slots", className: "text-center", defaultContent: "" },
					{ data: "ReportId", visible: false, defaultContent: "" },
					{ data: "Technician", defaultContent: "" },
					{ data: "StatusHtml", defaultContent: "" }
				],
				data: data
			});

			// wrap a parent row around top DOM
			$('.featuresSelectedData_wrapper .columns').wrapAll("<div class='row expanded align-middle' />");
			// add a delete button
			$('div.toolbarFeatures:first').html("<div class='button-group expanded'><a href='#' id='selectAll' class='button secondary margin-bottom-0 margin-right-1 selectAll' title='Select all rows'><i class='fas fa-line-columns'></i> Select all</a><a href='#' id='deletedSelected' class='button secondary margin-bottom-0 deletedSelected' disabled='disabled' title='Select rows to use delete'><i class='far fa-trash-alt'></i> Delete <span id='countRowSelected' class='show-for-sr'></span> selected</a></div>");

			plugin.$deleteSelectedButton = $('#selectedFeaturesPanel .deletedSelected');

			plugin.$selectAllButton = $('#selectedFeaturesPanel .selectAll');

			// delete job row(s) button
			plugin.$deleteSelectedButton.click(function () {

				plugin.selectedTable.rows('.selected').remove().draw(false);
				$('#countRowSelected').html(0).addClass('show-for-sr');

				$('th.sorting').focus();
				$(this).attr("disabled", "disabled").attr("title", "Select rows to use delete");
				plugin.$assignSelectedBtn.attr("disabled", "disabled").attr("title", "Select rows to assign");

			});

			plugin.$selectAllButton.click(function () {

				plugin.selectedTable.rows({ page: 'current' }).select();

			});

			// count the selected job rows
			plugin.selectedTable.on('select', function (e, dt, type, indexes) {

				var count = plugin.selectedTable.rows({ selected: true }).count();

				$('#countRowSelected').html(count);

				if (count > 0) {
					plugin.$deleteSelectedButton.removeAttr('disabled').attr("title", "");;
					$('#countRowSelected').removeClass('show-for-sr');

					plugin.$assignSelectedBtn.removeAttr('disabled').attr("title", "");

				}

			});

			plugin.selectedTable.on('deselect', function (e, dt, type, indexes) {

				var count = plugin.selectedTable.rows({ selected: true }).count();

				$('#countRowSelected').html(count);

				if (count < 1) {

					plugin.$deleteSelectedButton.attr("disabled", "disabled").attr("title", "Select rows to use delete");
					$('#countRowSelected').addClass('show-for-sr');

					plugin.$assignSelectedBtn.attr("disabled", "disabled").attr("title", "Select rows to assign");

					plugin.cancelTechicianSelection();
				}
			});

		},

		setupTechicianTable: function () {
			var plugin = this;

			plugin.assignTechniciansTable = plugin.$assignmentTable.DataTable({
				rowId: 'UserId',
				"ajax": {
					"url": '/admin/pestcontrol_appointment/SchedulerTechnicianData',
					"type": 'GET',
					"data": function (d) { return { "date": plugin.dateQueryString }; }
				},
				searching: false,
				retrieve: true,
				paging: false,
				ordering: true,
				info: true,
				scrollY: "50vh",
				scrollX: true,
				scrollCollapse: true,
				select: {
					style: 'single'
				},
				"createdRow": function (row, data, index) {
					if (data.NonSelectableRow) {
						$(row).addClass('noSelect');
					}
				},
				language: {
					emptyTable: "<div class='callout warning rounded text-center'><p class'h4'>No technician selected</p></div>",
					sZeroRecords: "<div class='callout warning rounded text-center'><p class'h4'>No matching technicians selected</p></div>",
					sInfo: "_TOTAL_ technicians to choose from:",
					select: {
						rows: {
							0: "Click a technician below to assign selected jobs from above",
							1: "1 technician selected"
						}
					}
				},
				dom: '<"topInfo columns large-9"i><"toolbarFeatures columns large-3">rt<"bottom"flp>',
				columns: [
					{ data: 'FirstName' },
					{ data: 'Surname' },
					{ data: 'AmSlots', className: 'textCenter' },
					{ data: 'PmSlots', className: 'textCenter' },
					{ data: 'CompletedAmSlots', className: 'textCenter' },
					{ data: 'CompletedPmSlots', className: 'textCenter' },
					{ data: 'Available' }]
				,
				order: [0, "asc"],
				columnDefs: [
					{ targets: 'no-sort', orderable: false },
				]
			});

			// wrap a parent row around top DOM
			$('.assignTechs_wrapper .columns').wrapAll("<div class='row expanded align-middle' />");

			// count the selected row
			plugin.assignTechniciansTable.on('select', function (e, dt, type, indexes) {

				var count = plugin.assignTechniciansTable.rows({ selected: true }).count();

				if (count > 0) {

					plugin.$assignTechBtn.removeAttr('disabled').attr("title", "");

				}

			});

			plugin.assignTechniciansTable.on('deselect', function (e, dt, type, indexes) {

				var count = plugin.assignTechniciansTable.rows({ selected: true }).count();

				if (count < 1) {

					plugin.$assignTechBtn.attr("title", "Select a row to confirm technician").attr("disabled", "disabled");

				}

			});

		},

		assignAppointments: function () {
			var plugin = this;

			plugin.showAssignWaitingMessage();

			var appointments = plugin.selectedTable.rows({ selected: true }).data();

			var ids = [];

			$.each(appointments, function (i, item) {
				console.log("id is " + item.AppointmentId);

				ids.push(item.AppointmentId);
			});

			if (ids.length == 0) {
				plugin.showAssignErrorMessage("Assignment Error", "No appointments have been selected");
				return;
			}

			var techRow = plugin.assignTechniciansTable.rows({ selected: true }).data();

			if (techRow.length === 0) {
				plugin.showAssignErrorMessage("Assignment Error", "No technician have been selected");
				return;
			}

			var id = techRow[0].UserId;

			var data = {
				userId: id,
				appointmentIds: ids
			};

			$.ajax({
				type: "POST",
				url: "/admin/pestcontrol_appointment/BlockAssignment",
				data: JSON.stringify(data),
				dataType: "json",
				contentType: "application/json; charset=utf-8",
				cache: false,
				success: function (data) {
					var message = '';

					if (data === null) {
						message = "An error has occurred whilst trying to confirm the success of the assignment.";
					} else {
						if (typeof data.message !== "string") {
							message =
								"An error has occurred whilst trying to confirm the success of the assignment.";
						} else {

							if (data.success === false) {
								message = data.message;
							}

							console.log(data.message);
						}
					}

					if (message.length > 0) {
						plugin.showAssignErrorMessage("Assignment Error", message);
					} else {
						plugin.assignTechniciansTable.ajax.reload(null, false);

						if (isNullOrWhiteSpace(plugin.dateQueryString)) {
							location.reload();
						} else {
							plugin.reloadData(false);
						}

						plugin.cancelSelectionPanel();
					}

				},
				error: function (jqXHR, textStatus, errorThrown) {

					plugin.showAssignErrorMessage("Internal Server Error", "A problem prevented the assignment from happening: " + textStatus);

				},
				complete: function () {

					plugin.selectedTable.rows('.selected').deselect();

					plugin.assignTechniciansTable.rows('.selected').deselect();

					plugin.selectedTable.clear();

				}
			});
		},

		cancelTechicianSelection: function () {
			var plugin = this;

			plugin.$assignSelectedBtn.attr("aria-expanded", "false").show();
			$('#assignTechPanel').hide();

			plugin.$assignTechBtn.hide();

		},

		showTechicianSelection: function () {
			var plugin = this;

			plugin.$assignSelectedBtn.attr("aria-expanded", "true").hide();
			$('#assignTechPanel').fadeIn(1000);

			$("#selectedFeaturesPanel").scrollTop($("#selectedFeaturesPanel")[0].scrollHeight);
			plugin.$assignTechBtn.fadeIn(1000).attr("aria-hidden", "false").attr("title", "Select a row to confirm technician");

			plugin.redrawTechniciansDatatable();
		},

		redrawTechniciansDatatable: function () {
			var plugin = this;

			plugin.assignTechniciansTable.ajax.reload(null, false);
		},

		assignTechician: function () {
			var plugin = this;


		},

		cancelSelectionPanel: function () {
			var plugin = this;

			// close bottom off canvas
			$('#selectedFeaturesPanel').foundation('toggle', 'close');

			// reset the assign selected button and hide the panel it opens
			plugin.$assignSelectedBtn.attr("disabled", "disabled").attr("title", "Select rows to assign").attr("aria-expanded", "false").show();

			$("#assignTechPanel").hide();

			// scroll to the top of the off canvas panel for the prototype
			$("#selectedFeaturesPanel").animate({
				scrollTop: 0
			});

			if (plugin.selectedTable !== null) {
				plugin.selectedTable.clear().destroy();
				plugin.selectedTable = null;
			}

			//set the hidden button back
			$('#confirmAssign').hide().attr("aria-hidden", "true").attr("title", "Select a row to confirm technician").attr("disabled", "disabled");

			plugin.$assignTechBtn.hide();
		},

		setupMapFeatureSelection: function() {

			var plugin = this;

			if (plugin.options.mapFeatureSelection !== true) {
				return;
			}

			//var select = new ol.interaction.Select();
			//plugin.options.map.addInteraction(select);

			var selectedFeatures = plugin.options.selectClick.getFeatures();

			// a DragBox interaction used to select features by drawing boxes
			var dragBox = new ol.interaction.DragBox({
				condition: ol.events.condition.platformModifierKeyOnly
			});

			plugin.options.map.addInteraction(dragBox);

			dragBox.on('boxend', function () {
				console.log("boxend");

				var extent = dragBox.getGeometry().getExtent();

				plugin.vectorSource.forEachFeatureIntersectingExtent(extent, function (feature) {
					selectedFeatures.push(feature);

					var selectedIconStyle = new ol.style.Style({
						image: new ol.style.Icon(({
							anchorOrigin: "top-left",
							src: "https://cdn.mapmarker.io/api/v1/fa/stack?size=120&icon=fa-star&color=%23FFFFFF&on=fa-circle&oncolor=%23FE9200&hoffset=1&voffset=0&iconsize=35"
						}))

					});

					//feature.setStyle(selectedIconStyle);

				});

				var data = selectedFeatures.getArray().map(function (feature) {
					var appointmentId = feature.get('appointmentId');
					var addressHtml = feature.get('addressHtml');
					var timePeriod = feature.get('timePeriod');
					var diary = feature.get('diary');
					var slots = feature.get('slots');
					var reportId = feature.get('reportId');
					var technician = feature.get('technician');
					var status = feature.get('status');

					var visible = !(feature.getStyle() == null || feature.getStyle().getImage() == null);

					return {
						AppointmentId: appointmentId,
						Address: addressHtml,
						TimePeriod: timePeriod,
						Diary: diary,
						Slots: slots,
						ReportId: reportId,
						Technician: technician,
						StatusHtml: status,
						Visible: visible
					};

				});

				for (var i = data.length - 1; i >= 0; --i) {
					var status = data[i].StatusHtml;

					if (status !== "Waiting" && status !== "Unassigned") {
						data.splice(i, 1);
						continue;
					}

					var visible = data[i].Visible;

					if (visible === false) {
						data.splice(i, 1);
					}
				}

				//var data2 = [];

				//$.each(arr, function (index, value) {

				//    if (val.StatusHtml !== "Assigned" && val.StatusHtml !== "Unassigned") {
				//        return;
				//    }

				//    data2.push(value);
				//});

				console.log("open assign panel");
				$('#selectedFeaturesPanel').foundation('toggle', 'open');

				plugin.setupSelectedAppointmentTable(data);

			});

			dragBox.on('boxstart', function () {
				console.log("boxstart");
				selectedFeatures.clear();
			});

		},

		setRegisterView: function (reload) {

			var plugin = this;

			if (plugin.table !== null) {
				plugin.table.destroy();
			}

			plugin.$appointmentTable.hide();
			plugin.$periodFilter.hide();
			plugin.$registerTable.show();

			plugin.currentView = "register";

			$("body").removeClass("schedulerLayout");

			$("body").addClass("registerLayout");

			var contentAreaHeight = $("#article").outerHeight() - 41;

			$("div.diaryHeader").hide();

			var data = null;

			if (plugin.DashboardData != null) {
				data = plugin.DashboardData.Technicians;
			}

			plugin.table = plugin.$registerTable.DataTable({
				"rowId": 'UserId',
				"sDom": "t",
				"dom": '<"toolbar">frtip',
				"retrieve": true,
				"paging": false,
				"ordering": true,
				"info": false,
				"scrollY": contentAreaHeight,
				"scrollX": true,
				"scrollCollapse": true,
				columns: [
					{ data: "TechnicianHtml", defaultContent: "" },
					{ data: "RosterStatus", defaultContent: "" },
					{ data: "CheckInTimeHtml", className: "textCenter", defaultContent: "" },
					{ data: "CheckOutTimeHtml", className: "textCenter", defaultContent: "" },
					{ data: "JobLocationHtml", defaultContent: "" },
					{ data: "Assigned", className: "textCenter", defaultContent: "", searchable: false },
					{ data: "Completed", className: "textCenter", defaultContent: "", searchable: false }
				],
				select: {
					style: "single"
				},
				"createdRow": function (row, data, index) {
					if (data.NonSelectableRow) {
						$(row).addClass("noSelect");
					}
				},
				data: data
			});

			plugin.table.on("select", function (e, dt, type, indexes) {
				if (type === "row") {
					var rows = plugin.table.rows(indexes).nodes().to$();
					$.each(rows, function () {
						if ($(this).hasClass("noSelect"))
							plugin.table.row($(this)).deselect();
					});
				}

				var techRow = plugin.table.rows({ selected: true }).data();

				if (techRow.length !== 1) {
					return;
				}

				var id = techRow[0].UserId;

				plugin.zoomToUser(id);
			});

			plugin.table.on("search.dt", function () {

				if (plugin.table == null) {
					return;
				}

				plugin.registerSearch = plugin.table.search();

				console.log("r search is " + plugin.table.search());

				var users = plugin.table.rows({ search: "applied" }).data();

				var ids = [];

				$.each(users, function (i, item) {
					ids.push(item.UserId);
				});

				plugin.filterUserMarkers(ids);

			});

			$("div.toolbar").html('<p>Technicians Register</p>');
			$(".dataTables_filter input").attr("placeholder", "Type and search...");

			$(".registerTable tbody").on("click", "tr", function () {

				var trAlert = plugin.table.rows(".selected").data().length;

				//$(this).toggleClass('selected');

				console.log(trAlert + " row(s) selected");

				if ($(this).hasClass("selected")) {
					$(this).removeClass("selected");
				}
				else {
					plugin.table.$("tr.selected").removeClass("selected");
					$(this).addClass("selected");
				}

			});

			if (plugin.options.map == null) {
				return;
			}

			plugin.options.map.updateSize();

			if (plugin.vectorLayer != null) {
				plugin.options.map.removeLayer(plugin.vectorLayer);
			}

			if (plugin.alertLocationVectorLayer != null) {
				plugin.options.map.removeLayer(plugin.alertLocationVectorLayer);
				plugin.alertLocationVectorLayer = null;
			}

			var vectorSource = new ol.source.Vector({
				features: []
			});

			var vectorLayer = new ol.layer.Vector({
				source: vectorSource,
				name: 'Techs'
			});

			var techLocationVectorSource = new ol.source.Vector({
				features: []
			});

			var techLocationVectorLayer = new ol.layer.Vector({
				source: techLocationVectorSource,
				name: 'CheckInFiltered'
			});

			plugin.vectorLayer = vectorLayer;
			plugin.vectorSource = vectorSource;

			plugin.techLocationVectorLayer = techLocationVectorLayer;
			plugin.techLocationVectorSource = techLocationVectorSource;

			plugin.options.map.addLayer(plugin.vectorLayer);
			plugin.options.map.addLayer(plugin.techLocationVectorLayer);

			var extent = new ol.extent.createEmpty();

			var markers = 0;

			$.each(data, function (key, val) {

				var easting = parseFloat(val.Easting);
				var northing = parseFloat(val.Northing);

				if (isNaN(easting) || isNaN(northing) || typeof val.PinSrc === "undefined") {
					return;
				}

				var checkInEasting = parseInt(val.CheckInEasting);
				var checkInNorhing = parseInt(val.CheckInNorthing);

				var checkOutEasting = parseInt(val.CheckOutEasting);
				var checkOutNorhing = parseInt(val.CheckOutNorthing);

				var newMarker = new ol.Feature({
					geometry: new ol.geom.Point([easting, northing]),
					appointmentId: val.AppointmentId,
					markerType: "techMarker",
					userId: val.UserId,
					address: val.PinTitle,
					postcode: val.PostalCode,
					technician: val.Name,
					status: val.StatusText,
					assigned: val.Assigned,
					completed: val.Completed,
					time: val.Time,
					timeLabel: val.TimeLabel,
					pin: val.PinSrc,
					checkInTime: val.CheckInTime,
					checkOutTime: val.CheckOutTime,
					checkInEasting: checkInEasting,
					checkInNorthing: checkInNorhing,
					checkOutEasting: checkOutEasting,
					checkOutNorthing: checkOutNorhing
				});

				var newIconStyle = new ol.style.Style({

					image: new ol.style.Icon(({
						anchorOrigin: 'top-left',
						src: val.PinSrc
					}))

				});

				newMarker.setStyle(newIconStyle);
				vectorSource.addFeature(newMarker);

				extent = new ol.extent.extend(extent, newMarker.getGeometry().getExtent());

				markers++;
			});

			if (markers > 0 && reload === false) {
				plugin.options.map.getView().fit(extent);
			}

			// https://stackoverflow.com/questions/49746970/openlayers-4-fit-to-extent-of-selected-features

			if (plugin.options.mapPopupOverlay == null) {
				return;
			}

			if (plugin.options.selectClick != null) {
				plugin.options.map.removeInteraction(plugin.options.selectClick);
			}

			var content = document.getElementById('popup-content');

			var selectClick = new ol.interaction.Select({

			});

			plugin.options.selectClick = selectClick;

			plugin.options.map.addInteraction(selectClick);

			selectClick.on("select", function (e) {

				var features = e.target.getFeatures();

				if (features.getLength() < 1) {
					return;
				}

				var feature = features.getArray()[0];

				var markerType = feature.get("markerType");
				var html = '';

				console.log("Marker: " + markerType);

				var coordinate = feature.getGeometry().getCoordinates();

				if (markerType === "techMarker") {

					var address = feature.get("address");
					var postcode = feature.get("postcode");
					var technician = feature.get("technician");
					var userId = feature.get("userId");
					var status = feature.get("status");
					var assigned = feature.get("assigned");
					var completed = feature.get("completed");
					var time = feature.get("time");
					var timeLabel = feature.get("timeLabel");
					var checkInTime = feature.get("checkInTime");
					var checkOutTime = feature.get("checkOutTime");

					var checkInEasting = feature.get("checkInEasting");
					var checkInNorthing = feature.get("checkInNorthing");

					var checkOutEasting = feature.get("checkOutEasting");
					var checkOutNorthing = feature.get("checkOutNorthing");

					html = '<p class="pinTitle">' + address + "</p>";

					if (isNullOrWhiteSpace(postcode) === false) {
						html += '<p class="pinPostcode">' + postcode + "</p>";
					}

					if (isNullOrWhiteSpace(technician) === false) {
						html += '<p class="row"><span class="columns small-6 labelVal">Technician</span><span class="columns small-6 valueVal">' + technician + "</span></p>";
					}

					if (isNullOrUndefined(assigned) === false) {
						html += '<p class="row"><span class="columns small-6 labelVal">Assigned</span><span class="columns small-6 valueVal">' + assigned + "</span></p>";
					}

					if (isNullOrUndefined(completed) === false) {
						html += '<p class="row"><span class="columns small-6 labelVal">Completed</span><span class="columns small-6 valueVal">' + completed + "</span></p>";
					}

					if (isNullOrWhiteSpace(status) === false) {
						html += '<p class="row"><span class="columns small-6 labelVal">Status</span><span class="columns small-6 valueVal">' + status + "</span></p>";
					}

					if (isNullOrWhiteSpace(timeLabel) === false && isNullOrWhiteSpace(time) === false) {
						html += '<p class="row"><span class="columns small-6 labelVal">' + timeLabel + '</span><span class="columns small-6 valueVal">' + time + "</span></p>";
					}

					if (isNullOrWhiteSpace(checkInTime) == false || isNullOrWhiteSpace(checkOutTime) == false) {

						if (isNullOrWhiteSpace(checkInTime) == false) {
							html += '<p class="row"><span class="columns small-6 labelVal">Check in</span><span class="columns small-6 valueVal">' + checkInTime;

							if (isNaN(checkInEasting) || isNaN(checkInNorthing)) {
								html += "</span></p>";
							} else {
								html += ' <img src="https://cdn.mapmarker.io/api/v1/fa/stack?size=120&amp;icon=fa-map-pin&amp;color=%23FFFFFF&amp;on=fa-circle&amp;oncolor=%23009CE0&amp;hoffset=1&amp;voffset=0&amp;iconsize=50&amp;" alt="View on map" width="34" height="34">' +
									"</span></p>";
							}
						}

						if (isNullOrWhiteSpace(checkOutTime) == false) {
							html += '<p class="row"><span class="columns small-6 labelVal">Check out</span><span class="columns small-6 valueVal">' + checkInTime;

							if (isNaN(checkOutEasting) || isNaN(checkOutNorthing)) {
								html += "</span></p>";
							} else {
								html += ' <img src="https://cdn.mapmarker.io/api/v1/fa/stack?size=120&amp;icon=fa-map-pin&amp;color=%23FFFFFF&amp;on=fa-circle&amp;oncolor=%23333333&amp;hoffset=1&amp;voffset=0&amp;iconsize=50&amp;" alt="View on map" width="34" height="34">' +
									"</span></p>";
							}
						}

						if ((isNaN(checkInEasting) === false && isNaN(checkInNorthing) === false) ||
							(isNaN(checkOutEasting) === false && isNaN(checkOutNorthing) === false)) {
							html += '<p class="row align-middle"><span class="columns small-12 labelVal">' +
								'<button class="button rounded small expanded" id="showRegisterLayer" data-checkInEasting="' + checkInEasting + '" data-checkInNorthing="' + checkInNorthing + '" data-checkOutEasting="' + checkOutEasting + '" data-checkOutNorthing="' + checkOutNorthing + '"><i class="fas fa-map-pin"></i> show check in / out</button></span></p></div>';
						}
					}

					content.innerHTML = html;

					plugin.techSelectedOnMap = technician;
					plugin.techSelectedOnMapCheckInTime = checkInTime;
					plugin.techSelectedOnMapCheckOutTime = checkOutTime;
					plugin.techSelectedUserId = userId;

					$("#showRegisterLayer").on("click", function (e) {
						var $this = $(this);

						plugin.showHideTechLocations($this);
					});

				} else {
					var technician = feature.get("technician");
					var checkInType = feature.get("appCheckin");
					var time = feature.get("time");

					html = '<p class="pinTitle">' + checkInType + '</p><p class="row"><span class="columns small-6 labelVal">Technician</span><span class="columns small-6 valueVal">' + technician + '</span></p><p class="row align-top"><span class="columns small-6 labelVal">Time</span><span class="columns small-6 valueVal">' + time + '</span></p>';

					content.innerHTML = html;
				}

				plugin.options.mapPopupOverlay.setPosition(coordinate);

				features.clear();

			});

			if (isNullOrWhiteSpace(plugin.registerSearch) === false) {
				plugin.table.search(plugin.registerSearch);
			}

		},

		clearReportedLayer: function () {

			var plugin = this;

			if (plugin.alertLocationVectorLayer == null) {
				return;
			}

			// remove existing
			$.each(plugin.alertLocationVectorLayer.features, function (idx, val) {

				plugin.alertLocationVectorSource.removeFeature(val);

			});

		},

		setReportedPosition: function (reportedEasting, reportedNorthing, technicianName, address, addressCoordinate) {

			var plugin = this;

			if (plugin.alertLocationVectorLayer == null || plugin.alertSelectedOnMapAddress == null) {
				return;
			}

			plugin.clearReportedLayer();

			var reportedPin = new ol.Feature({
				geometry: new ol.geom.Point([reportedEasting, reportedNorthing]),
				markerType: "reportedMarker",
				technician: technicianName,
				address: address

			});

			var reportedPinStyle = new ol.style.Style({
				image: new ol.style.Icon(({
					anchorOrigin: 'top-left',
					src: "https://cdn.mapmarker.io/api/v1/fa/stack?size=45&icon=fa-map-pin&color=%23FFF000&on=fa-circle&oncolor=%23009CE&hoffset=0&voffset=0&iconsize=16&"
				}))
			});

			reportedPin.setStyle(reportedPinStyle);

			plugin.alertLocationVectorSource.addFeature(reportedPin);

			var endPoint = new Array(2);

			endPoint[0] = reportedEasting;
			endPoint[1] = reportedNorthing;

			var lineStyle = [
				// linestring
				new ol.style.Style({
					stroke: new ol.style.Stroke({
						color: '#000000',
						width: 2
					})
				})
			];

			var lineFeature = new ol.Feature(new ol.geom.LineString([addressCoordinate, endPoint]));


			var line = new ol.Feature({
				geometry: new ol.geom.LineString(addressCoordinate, endPoint),
				name: 'Line',
				markerType: "Line",
			});

			lineFeature.setStyle(lineStyle);

			plugin.alertLocationVectorSource.addFeature(lineFeature);

			plugin.alertLocationVectorLayer.setVisible(true);
		},

		showHideAlertLocation: function ($btn) {

			console.log("showHideAlertLocation fn");

			var plugin = this;

			if (plugin.alertLocationVectorLayer == null || plugin.alertSelectedOnMapAddress == null) {
				return;
			}

			if (plugin.alertLocationVectorSourceAppointmentId != plugin.alertSelectedAppointmentId) {
				// remove existing
				$.each(plugin.alertLocationVectorLayer.features, function (idx, val) {

					plugin.alertLocationVectorSource.removeFeature(val);

				});
			}

			$btn.toggleClass('toggled');

			if ($btn.hasClass('toggled')) {

				$btn.html("<i class='fas fa-map-pin'></i> hide report location");

				if (plugin.alertLocationVectorSourceAppointmentId == plugin.alertSelectedAppointmentId) {
					plugin.alertLocationVectorLayer.setVisible(true);
					return;
				}

			} else {

				$btn.html("<i class='fas fa-map-pin'></i> show report location");

				if (plugin.alertLocationVectorSourceAppointmentId == plugin.alertSelectedAppointmentId) {
					plugin.alertLocationVectorLayer.setVisible(false);
				}

				return;
			}

			var reportedEasting = parseFloat($btn.data("reportedeasting"));
			var reportedNorthing = parseFloat($btn.data("reportednorthing"));

			var technicianName = plugin.alertSelectedOnMapTech;
			var address = plugin.alertSelectedOnMapAddress;

			if (isNaN(reportedEasting) === false && isNaN(reportedNorthing) === false) {

				var reportedPin = new ol.Feature({
					geometry: new ol.geom.Point([reportedEasting, reportedNorthing]),
					markerType: "reportedMarker",
					technician: technicianName,
					address: address

				});

				var reportedPinStyle = new ol.style.Style({
					image: new ol.style.Icon(({
						anchorOrigin: 'top-left',
						src: "https://cdn.mapmarker.io/api/v1/fa/stack?size=45&icon=fa-map-pin&color=%23FFF000&on=fa-circle&oncolor=%23009CE&hoffset=0&voffset=0&iconsize=16&"
					}))
				});

				reportedPin.setStyle(reportedPinStyle);

				plugin.alertLocationVectorSource.addFeature(reportedPin);
				plugin.alertLocationVectorLayer.setVisible(true);
			}

			plugin.alertLocationVectorSourceAppointmentId = plugin.alertSelectedAppointmentId;
		},

		showHideTechLocations: function ($btn) {

			var plugin = this;

			if (plugin.techLocationVectorLayer == null || plugin.techSelectedOnMap == null) {
				return;
			}

			if (plugin.techLocationVectorSourceUserId != plugin.techSelectedUserId) {
				// remove existing
				$.each(plugin.techLocationVectorLayer.features, function (idx, val) {

					plugin.techLocationVectorSource.removeFeature(val);

				});
			}

			$btn.toggleClass('toggled');

			if ($btn.hasClass('toggled')) {

				$btn.html("<i class='fas fa-map-pin'></i> hide check in / out");

				if (plugin.techLocationVectorSourceUserId == plugin.techSelectedUserId) {
					plugin.techLocationVectorLayer.setVisible(true);
					return;
				}

			} else {

				$btn.html("<i class='fas fa-map-pin'></i> show check in / out");

				if (plugin.techLocationVectorSourceUserId == plugin.techSelectedUserId) {
					plugin.techLocationVectorLayer.setVisible(false);
				}

				return;
			}

			var checkInEasting = parseFloat($btn.data("checkineasting"));
			var checkInNorthing = parseFloat($btn.data("checkinnorthing"));

			var checkOutEasting = parseFloat($btn.data("checkouteasting"));
			var checkOutNorthing = parseFloat($btn.data("checkoutnorthing"));

			var technicianName = plugin.techSelectedOnMap;

			if (isNaN(checkInEasting) === false && isNaN(checkInNorthing) === false) {

				var checkInTime = plugin.techSelectedOnMapCheckInTime;

				var checkInPin = new ol.Feature({
					geometry: new ol.geom.Point([checkInEasting, checkInNorthing]),
					markerType: "techCheckInOutMarker",
					appCheckin: "Check In",
					technician: technicianName,
					time: checkInTime

				});

				var checkInPinStyle = new ol.style.Style({
					image: new ol.style.Icon(({
						anchorOrigin: 'top-left',
						src: "https://cdn.mapmarker.io/api/v1/fa/stack?size=45&icon=fa-map-pin&color=%23FFFFFF&on=fa-circle&oncolor=%23009CE&hoffset=0&voffset=0&iconsize=16&"
					}))
				});

				checkInPin.setStyle(checkInPinStyle);

				plugin.techLocationVectorSource.addFeature(checkInPin);
			}

			if (isNaN(checkOutEasting) === false && isNaN(checkOutNorthing) === false) {

				var checkOutTime = plugin.techSelectedOnMapCheckOutTime;

				var checkOutPin = new ol.Feature({
					geometry: new ol.geom.Point([checkOutEasting, checkOutNorthing]),
					markerType: "techCheckInOutMarker",
					appCheckin: "Check Out",
					technician: technicianName,
					time: checkOutTime
				});

				var checkOutPinStyle = new ol.style.Style({
					image: new ol.style.Icon(({
						anchorOrigin: 'top-left',
						src: "https://cdn.mapmarker.io/api/v1/fa/stack?size=45&icon=fa-map-pin&color=%23FFFFFF&on=fa-circle&oncolor=%23333333&hoffset=0&voffset=0&iconsize=16&"
					}))
				});

				checkOutPin.setStyle(checkOutPinStyle);

				plugin.techLocationVectorSource.addFeature(checkOutPin);
			}

			plugin.techLocationVectorSourceUserId = plugin.techSelectedUserId;
		},

		zoomToAppointment: function(appointmentId) {

			var plugin = this;

			var feature = plugin.vectorSource.getFeatures().find(function (f) { return f.get("appointmentId") === appointmentId; });

			if (feature) {
				var extent = feature.getGeometry().getExtent();

				plugin.options.map.getView().fit(extent);

				//feature.setStyle(new ol.style.Style(null));

				//setTimeout(function() {

				//        var pinSrc = feature.get("pin");

				//        var iconStyle = new ol.style.Style({

				//            image: new ol.style.Icon(({
				//                anchorOrigin: "top-left",
				//                src: pinSrc
				//            }))
				//        });

				//        feature.setStyle(iconStyle);

				//    },
				//    2000);
			}
		},

		zoomToUser: function (userId) {

			var plugin = this;

			var feature = plugin.vectorSource.getFeatures().find(function (f) { return f.get("userId") === userId; });

			if (feature) {
				var extent = feature.getGeometry().getExtent();

				plugin.options.map.getView().fit(extent);
			}
		},

		setStatusCounts: function(counts) {
			var plugin = this;

			plugin.$statusWaiting.text(counts.WaitingCount);
			plugin.$statusComplete.text(counts.CompletedCount);
			plugin.$statusStarted.text(counts.StartedCount);
			plugin.$statusNoAccess.text(counts.NoAccessCount);
			plugin.$statusUnassigned.text(counts.UnassignedCount);
			plugin.$statusCancelled.text(counts.CancelledCount);
			plugin.$statusStopped.text(counts.StopCount);
			plugin.$statusCovid.text(counts.CovidCount);
			plugin.$statusAlert.text(counts.AlertCount);

		}

	});

	$.fn.pestDashboard = function (options) {

		var self = new pestDashboard(options);

		return this;
	};

	$.fn.pestDashboard.defaults = {
		dataRefreshUrl: null,
		autoRefreshSeconds: 360,
		errorAlertElementId: "#errorAlert",
		errorTitleElementId: "#errorModalTitle",
		errorMessageElementId: "#errorModalTitle",
		menuItemSelector: ".sideMenuItem",
		logoElementId: "#wlbtn",
		statusWaitingElementId: "#btnStatusNotStarted",
		statusCompleteElementId: "#btnStatusCompleted",
		statusStartedElementId: "#btnStatusStarted",
		statusNoAccessElementId: "#btnStatusNoAccess",
		statusUnassignedElementId: "#btnStatusUnassigned",
		statusCancelledElementId: "#btnStatusCancelled",
		statusStopElementId: "#btnStatusStop",
		statusCovidElementId: "#btnStatusCovid",
		statusAlertElementId: "#btnStatusAlert",
		statusButtonsSelector: "button.statBlock",
		activeStatusButtonsSelector: "button.statBlock.active",
		diaryButtonsSelector: "input.diaryBtn",
		periodButtonsSelector: ".periodBtn",
		activeDiaryButtonsSelector: "input.diaryBtn:checked",
		allButtonElementId: "#allDiaries",
		reloadButtonElementId: "#reloadBtn",
		autoReloadButtonElementId: "#hreloadBtn",
		appointmentTableElementId: "#mainScheduleTable",
		periodFilterContainerId: "#periodFilter",
		registerTableElementId: "#mainTechTable",
		showCheckInOutLocationButtonId: "#showRegisterLayer",
		selectedAppointmentTableElementId: "#featuresSelectedDataTable",
		selectedTechnicianTableElementId: "#assignTechsTable",
		cancelSelectionBtnElementId: "#cancelAssignBtn",
		cancelSelectionPanelCloseElementId: "#cancelAssign1",
		assignSelectedBtnElementId: "#assignSelectedBtn",
		assignTechBtnElementId: "#confirmAssignBtn",
		loaderPanelId: "#loaderFX",
		mapId: "map",
		mapPopupId: "popup",
		date: null,
		map: null,
		mapPopupOverlay: null,
		startDate: null,
		endDate: null,
		minDate: null,
		maxDate: null,
		mapFeatureSelection: true
	};

})(jQuery, window, document);
