'use strict';

/*
 * *******************************************************************************
 *  * Copyright (c) 2018 Edgeworx, Inc.
 *  *
 *  * This program and the accompanying materials are made available under the
 *  * terms of the Eclipse Public License v. 2.0 which is available at
 *  * http://www.eclipse.org/legal/epl-2.0
 *  *
 *  * SPDX-License-Identifier: EPL-2.0
 *  *******************************************************************************
 *
 */

//Set up background thread to refresh the info about the ioIntegrator instances
$(document).apwTimedAction({
	'actionFunction': 'getIntegratorList',
	'trackingElement': 'integratorlist',
	'timeOut': 0,
	'timerHandle': 'integratorListThread',
	'timeInterval': 5000
});

//Set up the global variables used for this screen session
apwDataManagerSetGlobalVariable("currentIntegrator", "");
apwDataManagerSetGlobalVariable("currentTrack", 0);
apwDataManagerSetGlobalVariable("currentStreamViewerURL", "");
apwDataManagerSetGlobalVariable("currentStreamViewerToken", "");
apwDataManagerSetGlobalVariable("currentConsoleURL", "");
apwDataManagerSetGlobalVariable("currentConsoleToken", "");

//Set up the click handler for the ioIntegrator instances
$(document).apwClickAction({
	'clickablesSelector': '#integratorlist li.auth-integrator-list-item',
	'actionFunction': 'clickIntegratorInstance',
	'loadDataFields': '{"instanceID":"instanceid"}'
});

//Set up the click handler for the tracks
$(document).apwClickAction({
	'clickablesSelector': '#tracklist li.auth-track-list-item',
	'actionFunction': 'clickTrack',
	'loadDataFields': '{"trackID":"trackid"}'
});

//Set up the click handler for the provisioning key buttons
$(document).apwClickAction({
	'clickablesSelector': '#integratorlist a.auth-provisioning-key-button',
	'actionFunction': 'clickProvisioningKey',
	'loadDataFields': '{"instanceID":"instanceid"}'
});

//Set up the click handler for the create integrator cancel button
$(document).apwClickAction({
	'clickablesSelector': '#auth-create-integrator-button-cancel',
	'actionFunction': 'clearCreateIntegratorForm'
});

//Set up the click handler for the create integrator confirm button
$(document).apwClickAction({
	'clickablesSelector': '#auth-create-integrator-button-confirm',
	'actionFunction': 'createNewIntegratorInstance'
});

//Set up the click handler for the update integrator instance buttons
$(document).apwClickAction({
	'clickablesSelector': '#integratorlist a.auth-update-integrator-instance-button',
	'actionFunction': 'clickUpdateIntegrator',
	'loadDataFields': '{"instanceID":"instanceid"}'
});

//Set up the click handler for the update integrator save button
$(document).apwClickAction({
	'clickablesSelector': '#auth-update-integrator-button-confirm',
	'actionFunction': 'saveUpdateIntegratorInstance'
});

//Set up the click handler for the delete integrator instance buttons
$(document).apwClickAction({
	'clickablesSelector': '#integratorlist a.auth-delete-integrator-instance-button',
	'actionFunction': 'clickDeleteIntegrator',
	'loadDataFields': '{"instanceID":"instanceid"}'
});

//Set up the click handler for the delete integrator confirm button
$(document).apwClickAction({
	'clickablesSelector': '#auth-delete-integrator-button-confirm',
	'actionFunction': 'confirmDeleteIntegratorInstance'
});

//Set up the click handler for the create track cancel button
$(document).apwClickAction({
	'clickablesSelector': '#auth-create-track-button-cancel',
	'actionFunction': 'clearCreateTrackForm'
});

//Set up the click handler for the create track confirm button
$(document).apwClickAction({
	'clickablesSelector': '#auth-create-track-button-confirm',
	'actionFunction': 'createNewTrack'
});

//Set up the click handler for the update track buttons
$(document).apwClickAction({
	'clickablesSelector': '#tracklist a.auth-update-track-button',
	'actionFunction': 'clickUpdateTrack',
	'loadDataFields': '{"trackID":"trackid"}'
});

//Set up the click handler for the update track save button
$(document).apwClickAction({
	'clickablesSelector': '#auth-update-track-button-confirm',
	'actionFunction': 'saveUpdateTrack'
});

//Set up the click handler for the delete track buttons
$(document).apwClickAction({
	'clickablesSelector': '#tracklist a.auth-delete-track-button',
	'actionFunction': 'clickDeleteTrack',
	'loadDataFields': '{"trackID":"trackid"}'
});

//Set up the click handler for the delete track confirm button
$(document).apwClickAction({
	'clickablesSelector': '#auth-delete-track-button-confirm',
	'actionFunction': 'confirmDeleteTrack'
});

//Set up the click handler for the delete element buttons
$(document).apwClickAction({
	'clickablesSelector': '#element-row-1 a.auth-delete-element-button',
	'actionFunction': 'clickDeleteElement',
	'loadDataFields': '{"elementID":"elementid"}'
});

//Set up the click handler for the delete element confirm button
$(document).apwClickAction({
	'clickablesSelector': '#auth-delete-element-button-confirm',
	'actionFunction': 'confirmDeleteElement'
});

//Set up the click handler for the create element main button (loads the catalog per instance id)
$(document).apwClickAction({
	'clickablesSelector': '#auth-element-main-add-button',
	'actionFunction': 'clickCreateElement',
	'loadDataFields': ''
});

//Set up the click handler for the create element confirm button
$(document).apwClickAction({
	'clickablesSelector': '#auth-create-element-button-confirm',
	'actionFunction': 'createNewElement'
});

//Set up the click handler for the update element buttons
$(document).apwClickAction({
	'clickablesSelector': '#element-row-1 a.auth-update-element-button',
	'actionFunction': 'clickUpdateElement',
	'loadDataFields': '{"elementID":"elementid"}'
});

//Set up the click handler for the update element save button
$(document).apwClickAction({
	'clickablesSelector': '#auth-update-element-button-confirm',
	'actionFunction': 'saveUpdateElement'
});

//Set up the click handler for the configure element buttons
$(document).apwClickAction({
	'clickablesSelector': '#element-row-1 a.auth-configure-element-button',
	'actionFunction': 'clickConfigureElement',
	'loadDataFields': '{"elementID":"elementid"}'
});

//Set up the click handler for the configure element save button
$(document).apwClickAction({
	'clickablesSelector': '#auth-configure-element-button-confirm',
	'actionFunction': 'saveConfigureElement'
});

//Set up the click handler for the manage ports element buttons
$(document).apwClickAction({
	'clickablesSelector': '#element-row-1 a.auth-port-element-button',
	'actionFunction': 'clickPortElement',
	'loadDataFields': '{"elementID":"elementid"}'
});

//Set up the click handler for the delete element port X buttons
$(document).apwClickAction({
	'clickablesSelector': '.auth-port-element-remove-port',
	'actionFunction': 'clickPortRemove',
	'loadDataFields': '{"portID":"portid","networkID":"networkid"}'
});

//Set up the click handler for the add element port button
$(document).apwClickAction({
	'clickablesSelector': '#auth-port-element-add-button',
	'actionFunction': 'clickPortAdd'
});

//Set up the click handler for the manage routes element buttons
$(document).apwClickAction({
	'clickablesSelector': '#element-row-1 a.auth-route-element-button',
	'actionFunction': 'clickRouteElement',
	'loadDataFields': '{"elementID":"elementid"}'
});

//Set up the click handler for the delete element route X buttons
$(document).apwClickAction({
	'clickablesSelector': '.auth-route-element-remove-output',
	'actionFunction': 'clickRouteRemove',
	'loadDataFields': '{"publishingInstance":"publishinginstance","publishingTrack":"publishingtrack","publishingElement":"publishingelement","destinationInstance":"destinationinstance","destinationTrack":"destinationtrack","destinationElement":"destinationelement"}'
});

//Set up the click handler for the add element route button
$(document).apwClickAction({
	'clickablesSelector': '#auth-route-element-output-add-button',
	'actionFunction': 'clickRouteAdd'
});

//Set up the click handler for the element output arrow button
$(document).apwClickAction({
	'clickablesSelector': '#element-list-output',
	'actionFunction': 'clickElementOutput'
});

function clickElementOutput() {
	if ($("#element-list-output").hasClass("devisualed")) {
		//Do nothing - we are not visible	
	} else {
		var lastID = $("#element-list-output").prev(".auth-element-list-item").data("elementid");

		var data = {};
		data.elementID = lastID;

		clickRouteElement(data);
	}
}

function clickRouteAdd() {
	var destEl = $("#auth-route-element-element-select").val();
	var destTra = $("#auth-route-element-track-select").val();
	var destIns = $("#auth-route-element-integrator-select").val();

	var pubEl = $("#auth-route-element-button-cancel").data("elementid");
	var pubTra = apwDataManagerGetGlobalVariable("currentTrack");
	var pubIns = apwDataManagerGetGlobalVariable("currentIntegrator");

	if (destTra > 0 && destEl != "INVALID") {
		var apiEndpointAddRoute = 'https://iofog.org/api/v1/authoring/element/instance/route/create';

		var updateFields = "PublishingInstanceID=" + pubIns + "&PublishingTrackID=" + pubTra + "&PublishingElementID=" + pubEl + "&DestinationInstanceID=" + destIns + "&DestinationTrackID=" + destTra + "&DestinationElementID=" + destEl;

		$(document).apwManualPostUp({
			'postingDisplayFunction': 'apwManualPostUpPostingDisplayBlank',
			'postingFinishDisplayFunction': 'apwManualPostUpPostingDisplayFinishBlank',
			'postingResponseHandlerFunction': 'addRouteAPI',
			'passToken': 'Y',
			'postURL': apiEndpointAddRoute,
			'postFailedFunction': 'addRouteAPIFail',
			'postData': updateFields
		});
	} else {
		alert("You cannot add a new routing output without a valid track and element selection.");
	}
}

function addRouteAPI(response) {
	var respObj = $.parseJSON(response);

	if (respObj.status == "ok") {
		var theRoute = respObj.route;

		//Get the elementID behind all this
		var curElementID = $("#auth-route-element-button-cancel").data("elementid");
		var lookString2 = "#element-list-item-" + curElementID;
		var curElement = $(lookString2);

		var fullObject = curElement.data("fullinfo");

		var routingCopy = fullObject.routing;

		//Figure out which sub-section of the routing we need to append
		if (theRoute.instanceid.length > 0) {
			routingCopy.outputs.extraintegrator.push(theRoute);
		} else if (theRoute.trackid > 0) {
			routingCopy.outputs.extratrack.push(theRoute);
		} else {
			routingCopy.outputs.intratrack.push(theRoute);
		}

		fullObject.routing = routingCopy;
		$(curElement).data("fullinfo", fullObject);

		//See if the new destination element is currently on the screen. If so, add this input to its data
		var lookString3 = "#element-list-item-" + theRoute.elementid;
		var destElementScreen = $(lookString3);

		if (destElementScreen.length) {
			var fullObject3 = destElementScreen.data("fullinfo");
			var routingCopy3 = fullObject3.routing;

			var theNewInput = {};
			theNewInput.elementid = curElementID;
			theNewInput.elementname = curElement.find(".auth-element-name").text();
			theNewInput.elementtypename = curElement.find(".auth-element-typename").text();

			routingCopy3.inputs.intratrack.push(theNewInput);

			fullObject3.routing = routingCopy3;
			$(destElementScreen).data("fullinfo", fullObject3);
		}

		//Now create the visual and place it on the screen
		var outputStartingPoint = $("#auth-route-element-output-title");
		var currentInstance = apwDataManagerGetGlobalVariable("currentIntegrator");
		var currentTrack = apwDataManagerGetGlobalVariable("currentTrack");

		if (theRoute.instanceid.length > 0) {
			var curRoute = theRoute;

			var aNewRouteItem = $('<div class="input-field col s12 element-routes-output-item" id="element-routes-output-item-' + curRoute.elementid + '"><i class="fa fa-arrow-circle-up"></i> <span class="element-routes-output-figure deep-purple-text">' + curRoute.instancename + '</span> > <span class="element-routes-output-figure light-green-text">' + curRoute.trackname + '</span> > <span class="element-routes-output-figure cyan-text">' + curRoute.elementname + '</span><a class="materialize-red-text element-routes-margin-item element-routes-output-figure auth-route-element-remove-output" href="#" data-publishinginstance="' + currentInstance + '" data-publishingtrack="' + currentTrack + '" data-publishingelement="' + curElementID + '" data-destinationinstance="' + curRoute.instanceid + '" data-destinationtrack="' + curRoute.trackid + '" data-destinationelement="' + curRoute.elementid + '"><i class="fa fa-remove"></i></a></div>');

			outputStartingPoint.after(aNewRouteItem);
		} else if (theRoute.trackid > 0) {
			var curRoute = theRoute;

			var aNewRouteItem = $('<div class="input-field col s12 element-routes-output-item" id="element-routes-output-item-' + curRoute.elementid + '"><i class="fa fa-arrow-circle-up"></i> <span class="element-routes-output-figure light-green-text">' + curRoute.trackname + '</span> > <span class="element-routes-output-figure cyan-text">' + curRoute.elementname + '</span><a class="materialize-red-text element-routes-margin-item element-routes-output-figure auth-route-element-remove-output" href="#" data-publishinginstance="' + currentInstance + '" data-publishingtrack="' + currentTrack + '" data-publishingelement="' + curElementID + '" data-destinationinstance="' + currentInstance + '" data-destinationtrack="' + curRoute.trackid + '" data-destinationelement="' + curRoute.elementid + '"><i class="fa fa-remove"></i></a></div>');

			outputStartingPoint.after(aNewRouteItem);
		} else {
			var curRoute = theRoute;

			var aNewRouteItem = $('<div class="input-field col s12 element-routes-output-item" id="element-routes-output-item-' + curRoute.elementid + '"><i class="fa fa-arrow-circle-up"></i> <span class="element-routes-output-figure cyan-text">' + curRoute.elementname + '</span><a class="materialize-red-text element-routes-margin-item element-routes-output-figure auth-route-element-remove-output" href="#" data-publishinginstance="' + currentInstance + '" data-publishingtrack="' + currentTrack + '" data-publishingelement="' + curElementID + '" data-destinationinstance="' + currentInstance + '" data-destinationtrack="' + currentTrack + '" data-destinationelement="' + curRoute.elementid + '"><i class="fa fa-remove"></i></a></div>');

			outputStartingPoint.after(aNewRouteItem);
		}
	}
}

function clickRouteRemove(data) {
	var destEl = data.destinationElement;
	var destTra = data.destinationTrack;
	var destIns = data.destinationInstance;
	var pubEl = data.publishingElement;
	var pubTra = data.publishingTrack;
	var pubIns = data.publishingInstance;

	var apiEndpointRemoveRoute = 'https://iofog.org/api/v1/authoring/element/instance/route/delete';

	var updateFields = "PublishingInstanceID=" + pubIns + "&PublishingTrackID=" + pubTra + "&PublishingElementID=" + pubEl + "&DestinationInstanceID=" + destIns + "&DestinationTrackID=" + destTra + "&DestinationElementID=" + destEl;

	$(document).apwManualPostUp({
		'postingDisplayFunction': 'apwManualPostUpPostingDisplayBlank',
		'postingFinishDisplayFunction': 'apwManualPostUpPostingDisplayFinishBlank',
		'postingResponseHandlerFunction': 'removeRouteAPI',
		'passToken': 'Y',
		'postURL': apiEndpointRemoveRoute,
		'postFailedFunction': 'removeRouteAPIFail',
		'postData': updateFields
	});
}

function removeRouteAPI(response) {
	var respObj = $.parseJSON(response);

	if (respObj.status == "ok") {
		var pubIns = respObj.publishinginstanceid;
		var pubTra = respObj.publishingtrackid;
		var pubEl = respObj.publishingelementid;

		var destIns = respObj.destinationinstanceid;
		var destTra = respObj.destinationtrackid;
		var destEl = respObj.destinationelementid;

		//Fetch the screen object by its destination element id
		var lookString = "#element-routes-output-item-" + destEl;
		var curItemFromDOM = $(lookString);

		//Get the elementID behind all this
		var curElementID = $("#auth-route-element-button-cancel").data("elementid");
		var lookString2 = "#element-list-item-" + curElementID;
		var curElement = $(lookString2);

		var fullObject = curElement.data("fullinfo");

		var routingCopy = fullObject.routing;

		//See if the new destination element is currently on the screen. If so, add this input to its data
		var lookString3 = "#element-list-item-" + destEl;
		var destElementScreen = $(lookString3);

		if (destElementScreen.length) {
			var fullObject3 = destElementScreen.data("fullinfo");
			var routingCopy3 = fullObject3.routing;

			var matchID = curElementID;

			for (var i = 0; i < routingCopy3.inputs.intratrack.length; i++) {
				if (routingCopy3.inputs.intratrack[i].elementid == matchID) {
					routingCopy3.inputs.intratrack.splice(i, 1);
				}
			}

			fullObject3.routing = routingCopy3;
			$(destElementScreen).data("fullinfo", fullObject3);
		}

		//Figure out which sub-section of the routing we need to look at
		if (pubIns != destIns) {
			//Loop through the copy of the correct routing section and remove the matching item
			for (var i = 0; i < routingCopy.outputs.extraintegrator.length; i++) {
				if (routingCopy.outputs.extraintegrator[i].instanceid == destIns && routingCopy.outputs.extraintegrator[i].trackid == destTra && routingCopy.outputs.extraintegrator[i].elementid == destEl) {
					routingCopy.outputs.extraintegrator.splice(i, 1);
				}
			}
		} else if (pubTra != destTra) {
			//Loop through the copy of the correct routing section and remove the matching item
			for (var i = 0; i < routingCopy.outputs.extratrack.length; i++) {
				if (routingCopy.outputs.extratrack[i].trackid == destTra && routingCopy.outputs.extratrack[i].elementid == destEl) {
					routingCopy.outputs.extratrack.splice(i, 1);
				}
			}
		} else {
			//Loop through the copy of the correct routing section and remove the matching item
			for (var i = 0; i < routingCopy.outputs.intratrack.length; i++) {
				if (routingCopy.outputs.intratrack[i].elementid == destEl) {
					routingCopy.outputs.intratrack.splice(i, 1);
				}
			}
		}

		fullObject.routing = routingCopy;

		$(curElement).data("fullinfo", fullObject);
		curItemFromDOM.remove();
	}
}

function updateRoutingOutputAddBoxes(trackID, currentElementID) {
	//Get the currently selected integrator from that drop-down
	var currentIntegrator = $("#auth-route-element-integrator-select").val();

	//Store the incoming data into the select objects for retrieval on callback (it's a hack but it's OK for now)
	$("#auth-route-element-track-select").data("loadingtrackid", trackID);
	$("#auth-route-element-element-select").data("currentelementid", currentElementID);

	//Get the list of tracks for the currently selected integrator and populate the drop-down.
	//Set the chosen track if trackID > 0
	//Otherwise use the first track in the list
	//If there are no tracks, add an item that is disabled with a value of 0
	//and also update the element drop-down with a single disabled item with a value of ""
	var apiEndpointTracks = 'https://iofog.org/api/v1/authoring/integrator/track/list/instanceid/' + currentIntegrator;

	$(document).apwManualPostUp({
		'postingDisplayFunction': 'apwManualPostUpPostingDisplayBlank',
		'postingFinishDisplayFunction': 'apwManualPostUpPostingDisplayFinishBlank',
		'postingResponseHandlerFunction': 'updateRoutingOutputAddBoxesTracks',
		'passToken': 'Y',
		'postURL': apiEndpointTracks,
		'postFailedFunction': 'updateRoutingOutputAddBoxesTracksFail',
		'postData': ''
	});
}

function updateRoutingOutputAddBoxesTracks(response) {
	var respObj = $.parseJSON(response);

	if (respObj.status == "ok") {
		//Clear the input fields
		$("#auth-route-element-track-select").find("option").remove();
		$("#auth-route-element-element-select").find("option").remove();
		$("#auth-route-element-track-select-container").find("span.caret").remove();
		$("#auth-route-element-element-select-container").find("span.caret").remove();

		var tracks = respObj.tracks;

		//Get the chosen track data
		var chosenTrackID = $("#auth-route-element-track-select").data("loadingtrackid");
		var currentTrackID = apwDataManagerGetGlobalVariable("currentTrack");

		if (tracks.length > 0) {
			//Loop through the tracks and set the options
			for (var i = 0; i < tracks.length; i++) {
				var curTrack = tracks[i];
				var curTrackID = curTrack.id;
				var curTrackname = curTrack.name;

				var selString = "";
				var nameString = curTrackname;

				if (chosenTrackID > 0) {
					if (curTrackID == chosenTrackID) {
						selString = " selected";
					}
				} else {
					if (i == 0) {
						selString = " selected";
					}
				}

				if (curTrackID == currentTrackID) {
					nameString = "This track";
				}

				var aNewOption = $('<option value="' + curTrackID + '"' + selString + '>' + nameString + '</option>');

				$("#auth-route-element-track-select").append(aNewOption);
			}

			//Get the list of elements for the selected track and populate the drop-down.
			//Omit the currently active element (passed in as currentElementID) and
			//also omit any elements that already appear in the routing outputs for this element's data
			var theHighlightedTrackID = $("#auth-route-element-track-select").val();
			var apiEndpointElements = 'https://iofog.org/api/v1/authoring/integrator/track/element/list/trackid/' + theHighlightedTrackID;

			$(document).apwManualPostUp({
				'postingDisplayFunction': 'apwManualPostUpPostingDisplayBlank',
				'postingFinishDisplayFunction': 'apwManualPostUpPostingDisplayFinishBlank',
				'postingResponseHandlerFunction': 'updateRoutingOutputAddBoxesElements',
				'passToken': 'Y',
				'postURL': apiEndpointElements,
				'postFailedFunction': 'updateRoutingOutputAddBoxesElementsFail',
				'postData': ''
			});

			$("#auth-route-element-track-select").material_select();
		} else {
			var aNewOption = $('<option value="0" selected>No track avail.</option>');
			$("#auth-route-element-track-select").append(aNewOption);

			var aNewOption = $('<option value="INVALID" selected>No elements avail.</option>');
			$("#auth-route-element-element-select").append(aNewOption);

			$("#auth-route-element-track-select").material_select();
			$("#auth-route-element-element-select").material_select();
		}
	}
}

function updateRoutingOutputAddBoxesTracksStart() {
	//Clear the input fields
	$("#auth-route-element-element-select").find("option").remove();
	$("#auth-route-element-element-select-container").find("span.caret").remove();

	var chosenTrackID = $("#auth-route-element-track-select").val();

	var apiEndpointElements = 'https://iofog.org/api/v1/authoring/integrator/track/element/list/trackid/' + chosenTrackID;

	$(document).apwManualPostUp({
		'postingDisplayFunction': 'apwManualPostUpPostingDisplayBlank',
		'postingFinishDisplayFunction': 'apwManualPostUpPostingDisplayFinishBlank',
		'postingResponseHandlerFunction': 'updateRoutingOutputAddBoxesElements',
		'passToken': 'Y',
		'postURL': apiEndpointElements,
		'postFailedFunction': 'updateRoutingOutputAddBoxesElementsFail',
		'postData': ''
	});
}

function updateRoutingOutputAddBoxesElements(response) {
	var respObj = $.parseJSON(response);

	if (respObj.status == "ok") {
		var elements = respObj.elements;

		//Get the chosen track data
		var chosenTrackID = $("#auth-route-element-track-select").val();

		var currentElementID = $("#auth-route-element-element-select").data("currentelementid");

		if (elements.length > 0) {
			var createdElementCounter = 0;

			//Loop through the tracks and set the options
			for (var i = 0; i < elements.length; i++) {
				var curEl = elements[i];
				var curElID = curEl.elementid;
				var curElName = curEl.name;

				//Loop through the data for this element and see if this item is already in the output routing
				var foundItAlready = false;

				var lookString = "#element-list-item-" + currentElementID;
				var curItemFromDOM = $(lookString);
				var routing = curItemFromDOM.data("fullinfo").routing;

				for (var j = 0; j < routing.outputs.intratrack.length; j++) {
					if (routing.outputs.intratrack[j].elementid == curElID) {
						foundItAlready = true;
					}
				}

				for (var j = 0; j < routing.outputs.extratrack.length; j++) {
					if (routing.outputs.extratrack[j].elementid == curElID) {
						foundItAlready = true;
					}
				}

				for (var j = 0; j < routing.outputs.extraintegrator.length; j++) {
					if (routing.outputs.extraintegrator[j].elementid == curElID) {
						foundItAlready = true;
					}
				}

				if (curElID == currentElementID || foundItAlready == true) {
					//Do nothing - don't add this as an option
				} else {
					var selString = "";
					var nameString = curElName;

					if (i == 0) {
						selString = " selected";
					}

					var aNewOption = $('<option value="' + curElID + '"' + selString + '>' + nameString + '</option>');

					$("#auth-route-element-element-select").append(aNewOption);

					createdElementCounter++;
				}
			}

			if (createdElementCounter == 0) {
				var aNewOption = $('<option value="INVALID" selected>No elements avail.</option>');
				$("#auth-route-element-element-select").append(aNewOption);
			}
		} else {
			var aNewOption = $('<option value="INVALID" selected>No elements avail.</option>');
			$("#auth-route-element-element-select").append(aNewOption);
		}
	}

	$("#auth-route-element-element-select").material_select();
}

function clickRouteElement(data) {
	var elementID = data.elementID;

	//Clear the prior list of routes
	var routeContainer = $("#element-routes-container");
	//var portAnchor = $("#element-ports-anchor");
	routeContainer.find("div.element-routes-input-item").remove();
	routeContainer.find("div.element-routes-output-item").remove();

	//Get the current information about the ioIntegrator instance from the object itself
	var lookString = "#element-list-item-" + elementID;
	var curItemFromDOM = $(lookString);

	var currentIntegrator = apwDataManagerGetGlobalVariable("currentIntegrator");
	var integratorDropDownContainer = $("#auth-route-element-integrator-select");
	integratorDropDownContainer.find("option").remove();
	$("#auth-route-element-integrator-select-container").find("span.caret").remove();

	//Get the list of integrators from the screen and populate the drop-down.
	//Mark the currently active integrator as selected.
	var presentintegrators = $("#integratorlist li.auth-integrator-list-item");

	for (var i = 0; i < presentintegrators.length; i++) {
		if (i > 0) {
			var curInt = $(presentintegrators[i]);
			var curIntID = curInt.data("instanceid");
			var curIntName = curInt.find("div.auth-integrator-name").text();

			var selString = "";
			var nameString = curIntName;

			if (curIntID == currentIntegrator) {
				selString = " selected";
				nameString = "This integrator";
			}

			var aNewOption = $('<option value="' + curIntID + '"' + selString + '>' + nameString + '</option>');

			integratorDropDownContainer.append(aNewOption);
		}
	}

	//Call the materialize method for updating the visuals

	$("#auth-route-element-integrator-select").material_select('destroy');
	$("#auth-route-element-integrator-select").material_select();

	var currentTrack = apwDataManagerGetGlobalVariable("currentTrack");
	updateRoutingOutputAddBoxes(currentTrack, elementID);

	var routing;

	//If this item exists, get the data and then the configuration string
	if (curItemFromDOM.length) {
		routing = curItemFromDOM.data("fullinfo").routing;
	}

	var inputStartingPoint = $("#auth-route-element-input-title");

	for (var i = 0; i < routing.inputs.extraintegrator.length; i++) {
		var curRoute = routing.inputs.extraintegrator[i];

		var aNewRouteItem = $('<div class="input-field col s12 element-routes-input-item" id="element-routes-input-item-' + curRoute.elementid + '"><i class="fa fa-arrow-circle-down"></i> <span class="element-routes-input-figure deep-purple-text">' + curRoute.instancename + '</span> > <span class="element-routes-input-figure light-green-text">' + curRoute.trackname + '</span> > <span class="element-routes-input-figure cyan-text">' + curRoute.elementname + '</span></div>');

		inputStartingPoint.after(aNewRouteItem);
	}

	for (var i = 0; i < routing.inputs.extratrack.length; i++) {
		var curRoute = routing.inputs.extratrack[i];

		var aNewRouteItem = $('<div class="input-field col s12 element-routes-input-item" id="element-routes-input-item-' + curRoute.elementid + '"><i class="fa fa-arrow-circle-down"></i> <span class="element-routes-input-figure light-green-text">' + curRoute.trackname + '</span> > <span class="element-routes-input-figure cyan-text">' + curRoute.elementname + '</span></div>');

		inputStartingPoint.after(aNewRouteItem);
	}

	for (var i = 0; i < routing.inputs.intratrack.length; i++) {
		var curRoute = routing.inputs.intratrack[i];

		var aNewRouteItem = $('<div class="input-field col s12 element-routes-input-item" id="element-routes-input-item-' + curRoute.elementid + '"><i class="fa fa-arrow-circle-down"></i> <span class="element-routes-input-figure cyan-text">' + curRoute.elementname + '</span></div>');

		inputStartingPoint.after(aNewRouteItem);
	}

	var outputStartingPoint = $("#auth-route-element-output-title");
	var currentInstance = apwDataManagerGetGlobalVariable("currentIntegrator");
	var currentTrack = apwDataManagerGetGlobalVariable("currentTrack");

	for (var i = 0; i < routing.outputs.extraintegrator.length; i++) {
		var curRoute = routing.outputs.extraintegrator[i];

		var aNewRouteItem = $('<div class="input-field col s12 element-routes-output-item" id="element-routes-output-item-' + curRoute.elementid + '"><i class="fa fa-arrow-circle-up"></i> <span class="element-routes-output-figure deep-purple-text">' + curRoute.instancename + '</span> > <span class="element-routes-output-figure light-green-text">' + curRoute.trackname + '</span> > <span class="element-routes-output-figure cyan-text">' + curRoute.elementname + '</span><a class="materialize-red-text element-routes-margin-item element-routes-output-figure auth-route-element-remove-output" href="#" data-publishinginstance="' + currentInstance + '" data-publishingtrack="' + currentTrack + '" data-publishingelement="' + elementID + '" data-destinationinstance="' + curRoute.instanceid + '" data-destinationtrack="' + curRoute.trackid + '" data-destinationelement="' + curRoute.elementid + '"><i class="fa fa-remove"></i></a></div>');

		outputStartingPoint.after(aNewRouteItem);
	}

	for (var i = 0; i < routing.outputs.extratrack.length; i++) {
		var curRoute = routing.outputs.extratrack[i];

		var aNewRouteItem = $('<div class="input-field col s12 element-routes-output-item" id="element-routes-output-item-' + curRoute.elementid + '"><i class="fa fa-arrow-circle-up"></i> <span class="element-routes-output-figure light-green-text">' + curRoute.trackname + '</span> > <span class="element-routes-output-figure cyan-text">' + curRoute.elementname + '</span><a class="materialize-red-text element-routes-margin-item element-routes-output-figure auth-route-element-remove-output" href="#" data-publishinginstance="' + currentInstance + '" data-publishingtrack="' + currentTrack + '" data-publishingelement="' + elementID + '" data-destinationinstance="' + currentInstance + '" data-destinationtrack="' + curRoute.trackid + '" data-destinationelement="' + curRoute.elementid + '"><i class="fa fa-remove"></i></a></div>');

		outputStartingPoint.after(aNewRouteItem);
	}

	for (var i = 0; i < routing.outputs.intratrack.length; i++) {
		var curRoute = routing.outputs.intratrack[i];

		var aNewRouteItem = $('<div class="input-field col s12 element-routes-output-item" id="element-routes-output-item-' + curRoute.elementid + '"><i class="fa fa-arrow-circle-up"></i> <span class="element-routes-output-figure cyan-text">' + curRoute.elementname + '</span><a class="materialize-red-text element-routes-margin-item element-routes-output-figure auth-route-element-remove-output" href="#" data-publishinginstance="' + currentInstance + '" data-publishingtrack="' + currentTrack + '" data-publishingelement="' + elementID + '" data-destinationinstance="' + currentInstance + '" data-destinationtrack="' + currentTrack + '" data-destinationelement="' + curRoute.elementid + '"><i class="fa fa-remove"></i></a></div>');

		outputStartingPoint.after(aNewRouteItem);
	}

	//Put the information into the update element modal window
	//TBD
	$("#auth-route-element-button-cancel").data("elementid", elementID);
}

function clickPortAdd() {
	var elementID = $("#auth-port-element-button-cancel").data("elementid");
	var internalPort = $("#auth-port-element-internalport").val();
	var externalPort = $("#auth-port-element-externalport").val();
	var isPublicChecked = $("#auth-port-element-publicaccess").is(":checked");
	var publicAccess = 0;

	if (isPublicChecked) {
		publicAccess = 1;
	}

	//Check to see that both the internal and external ports are real numbers
	var internalPort = parseInt(internalPort);
	var externalPort = parseInt(externalPort);

	if (internalPort > 0 && externalPort > 0) {
		var apiEndpointAddPort = 'https://iofog.org/api/v1/authoring/element/instance/port/create';

		var updateFields = "ElementID=" + elementID + "&InternalPort=" + internalPort + "&ExternalPort=" + externalPort + "&PublicAccess=" + publicAccess + "&trackId=" + selectedTrackId;

		$(document).apwManualPostUp({
			'postingDisplayFunction': 'apwManualPostUpPostingDisplayBlank',
			'postingFinishDisplayFunction': 'apwManualPostUpPostingDisplayFinishBlank',
			'postingResponseHandlerFunction': 'addPortAPI',
			'passToken': 'Y',
			'postURL': apiEndpointAddPort,
			'postFailedFunction': 'addPortAPIFail',
			'postData': updateFields
		});
	} else {
		alert("You must enter a valid number for both the internal and external ports.");
	}
}

function addPortAPI(response) {
	var respObj = $.parseJSON(response);

	if (respObj.status == "ok") {
		var curPort = respObj.port;

		//Get the elementID behind all this and update its data
		var curElementID = $("#auth-port-element-button-cancel").data("elementid");
		var lookString2 = "#element-list-item-" + curElementID;
		var curElement = $(lookString2);

		var fullObject = curElement.data("fullinfo");

		var portsCopy = fullObject.openports;
		portsCopy.push(curPort);
		fullObject.openports = portsCopy;

		$(curElement).data("fullinfo", fullObject);

		//Clear the input fields
		$("#auth-port-element-internalport").val("");
		$("#auth-port-element-externalport").val("");
		$("#auth-port-element-publicaccess").attr('checked', false);

		//Create the new screen object and add it to the UI
		var portAnchor = $("#element-ports-anchor");
		var finalAccessString = "None (restricted to edge)";

		if (typeof curPort.accessurl != 'undefined') {
			if (curPort.accessurl.length > 0) {
				finalAccessString = curPort.accessurl;
			}
		}

		var aNewPortItem = $('<div class="input-field col s12 element-ports-item" id="element-ports-item-' + curPort.portid + '"><span class="element-ports-figure">Port inside element: ' + curPort.internalport + '</span><span class="element-ports-figure">Port exposed on edge: ' + curPort.externalport + '</span><span class="element-ports-figure">Public access URL: ' + finalAccessString + '</span><a class="materialize-red-text element-ports-figure auth-port-element-remove-port" href="#" data-portid="' + curPort.portid + '" data-networkid="' + curPort.networkpairingid + '"><i class="fa fa-remove"></i></a></div>');

		portAnchor.after(aNewPortItem);
	}
}

function clickPortRemove(data) {
	var portID = data.portID;
	var networkID = data.networkID;

	if (networkID > 0) {
		//Do nothing here - all good
	} else {
		networkID = 0;
	}

	var apiEndpointRemovePort = 'https://iofog.org/api/v1/authoring/element/instance/port/delete';

	var updateFields = "PortID=" + portID + "&NetworkPairingID=" + networkID;

	$(document).apwManualPostUp({
		'postingDisplayFunction': 'apwManualPostUpPostingDisplayBlank',
		'postingFinishDisplayFunction': 'apwManualPostUpPostingDisplayFinishBlank',
		'postingResponseHandlerFunction': 'removePortAPI',
		'passToken': 'Y',
		'postURL': apiEndpointRemovePort,
		'postFailedFunction': 'removePortAPIFail',
		'postData': updateFields
	});
}

function removePortAPI(response) {
	var respObj = $.parseJSON(response);

	if (respObj.status == "ok") {
		var thePortID = respObj.portid;

		//Fetch the screen object and update its fields accordingly
		var lookString = "#element-ports-item-" + thePortID;
		var curItemFromDOM = $(lookString);

		//Get the elementID behind all this
		var curElementID = $("#auth-port-element-button-cancel").data("elementid");
		var lookString2 = "#element-list-item-" + curElementID;
		var curElement = $(lookString2);

		var fullObject = curElement.data("fullinfo");

		var portsCopy = fullObject.openports;

		//Loop through the copy of the ports and remove the matching item
		for (var i = 0; i < portsCopy.length; i++) {
			if (portsCopy[i].portId == thePortID) {
				portsCopy.splice(i, 1);
			}
		}

		fullObject.openports = portsCopy;

		$(curElement).data("fullinfo", fullObject);
		curItemFromDOM.remove();
	}
}

function clickPortElement(data) {
	var elementID = data.elementID;

	//Clear the prior list of ports
	var portContainer = $("#element-ports-container");
	var portAnchor = $("#element-ports-anchor");
	portContainer.find("div.element-ports-item").remove();

	//Clear the input fields
	$("#auth-port-element-internalport").val("");
	$("#auth-port-element-externalport").val("");
	$("#auth-port-element-publicaccess").attr('checked', false);

	//Get the current information about the ioIntegrator instance from the object itself
	var lookString = "#element-list-item-" + elementID;
	var curItemFromDOM = $(lookString);

	var ports;

	//If this item exists, get the data and then the configuration string
	if (curItemFromDOM.length) {
		ports = curItemFromDOM.data("fullinfo").openports;
	}

	for (var i = 0; i < ports.length; i++) {
		var curPort = ports[i];

		var finalAccessString = "None (restricted to edge)";

		if (curPort.accessurl.length > 0) {
			finalAccessString = curPort.accessurl;
		}

		var aNewPortItem = $('<div class="input-field col s12 element-ports-item" id="element-ports-item-' + curPort.portid + '"><span class="element-ports-figure">Port inside element: ' + curPort.internalport + '</span><span class="element-ports-figure">Port exposed on edge: ' + curPort.externalport + '</span><span class="element-ports-figure">Public access URL: ' + finalAccessString + '</span><a class="materialize-red-text element-ports-figure auth-port-element-remove-port" href="#" data-portid="' + curPort.portid + '" data-networkid="' + curPort.networkpairingid + '"><i class="fa fa-remove"></i></a></div>');

		portAnchor.after(aNewPortItem);
	}

	//Put the information into the update element modal window
	//TBD
	$("#auth-port-element-button-cancel").data("elementid", elementID);
}

function saveConfigureElement() {
	var apiEndpointConfigureElement = 'https://iofog.org/api/v1/authoring/element/instance/config/update';

	var updateFields = "ElementID=";
	var iID = $("#auth-configure-element-config").data("elementid");
	var config = $("#auth-configure-element-config").val();

	updateFields += iID + "&Config=" + config;

	$(document).apwManualPostUp({
		'postingDisplayFunction': 'apwManualPostUpPostingDisplayBlank',
		'postingFinishDisplayFunction': 'apwManualPostUpPostingDisplayFinishBlank',
		'postingResponseHandlerFunction': 'configureElementAPI',
		'passToken': 'Y',
		'postURL': apiEndpointConfigureElement,
		'postFailedFunction': 'configureElementAPIFail',
		'postData': updateFields
	});
}

function configureElementAPI(response) {
	var respObj = $.parseJSON(response);

	if (respObj.status == "ok") {
		var theElementID = respObj.elementid;

		//Fetch the screen object and update its fields accordingly
		var lookString = "#element-list-item-" + theElementID;
		var curItemFromDOM = $(lookString);

		//Get the values out of the update form
		var config = $("#auth-configure-element-config").val();

		var fullObject = curItemFromDOM.data("fullinfo");
		fullObject.config = config;

		$(curItemFromDOM).data("fullinfo", fullObject);
	}
}

function clickConfigureElement(data) {
	var elementID = data.elementID;

	//Get the current information about the ioIntegrator instance from the object itself
	var lookString = "#element-list-item-" + elementID;
	var curItemFromDOM = $(lookString);

	var config = "";

	//If this item exists, get the data and then the configuration string
	if (curItemFromDOM.length) {
		config = curItemFromDOM.data("fullinfo").config;
	}

	//Put the information into the update element modal window
	$("#auth-configure-element-config").val(config);
	$("#auth-configure-element-config").data("elementid", elementID);
}

function saveUpdateElement() {
	var apiEndpointUpdateElement = 'https://iofog.org/api/v1/authoring/element/instance/name/update';

	var updateFields = "ElementID=";
	var iID = $("#auth-update-element-elementname").data("elementid");
	var iName = $("#auth-update-element-elementname").val();

	updateFields += iID + "&Name=" + iName;

	$(document).apwManualPostUp({
		'postingDisplayFunction': 'apwManualPostUpPostingDisplayBlank',
		'postingFinishDisplayFunction': 'apwManualPostUpPostingDisplayFinishBlank',
		'postingResponseHandlerFunction': 'updateElementAPI',
		'passToken': 'Y',
		'postURL': apiEndpointUpdateElement,
		'postFailedFunction': 'updateElementAPIFail',
		'postData': updateFields
	});
}

function updateElementAPI(response) {
	var respObj = $.parseJSON(response);

	if (respObj.status == "ok") {
		var theElementID = respObj.elementid;

		//Fetch the screen object and update its fields accordingly
		var lookString = "#element-list-item-" + theElementID;
		var curItemFromDOM = $(lookString);

		//Get the values out of the update form
		var iName = $("#auth-update-element-elementname").val();

		$(curItemFromDOM).find(".auth-element-name").text(iName);

		//Go through every element on the screen and see if we need to change our name in the routing
		var presentElements = $("#element-row-1 div.auth-element-list-item");

		for (var i = 0; i < presentElements.length; i++) {
			var tmpElement = presentElements[i];
			var tmpElementID = $(tmpElement).data("elementid");

			if (tmpElementID == "BLANK") {
				//Skip this one - it's the hidden anchor
			} else {
				//Get the routing from this element
				var fullObject = $(tmpElement).data("fullinfo");
				var routingCopy = fullObject.routing;
				var outLength = routingCopy.outputs.intratrack.length;
				var inLength = routingCopy.inputs.intratrack.length;
				//console.log("outLength was: " + outLength);
				//console.log("inLength was: " + inLength);
				for (var j = 0; j < outLength; j++) {
					var curRoute = routingCopy.outputs.intratrack[j];

					if (curRoute.elementid == theElementID) {
						//We have a match. Update the name
						routingCopy.outputs.intratrack[j].elementname = iName;
					}
				}

				for (var j = 0; j < inLength; j++) {
					var curRoute = routingCopy.inputs.intratrack[j];

					if (curRoute.elementid == theElementID) {
						//We have a match. Update the name
						routingCopy.inputs.intratrack[j].elementname = iName;
					}
				}

				fullObject.routing = routingCopy;
				$(tmpElement).data("fullinfo", fullObject);
			}
		}
	}
}

function clickUpdateElement(data) {
	var elementID = data.elementID;

	//Get the current information about the ioIntegrator instance from the object itself
	var lookString = "#element-list-item-" + elementID;
	var curItemFromDOM = $(lookString);

	var curName = "";

	//If this item exists, get the fields
	if (curItemFromDOM.length) {
		curName = curItemFromDOM.find(".auth-element-name").text();
	}

	//Put the information into the update element modal window
	$("#auth-update-element-elementname").val(curName);
	$("#auth-update-element-elementname").data("elementid", elementID);
}

function createNewElement() {
	var apiEndpointCreateElement = 'https://iofog.org/api/v1/authoring/element/instance/create';

	var createFields = "IntegratorInstanceID=";
	var iID = apwDataManagerGetGlobalVariable("currentIntegrator");
	var presentElements = $("#element-row-1 div.auth-element-list-item");
	var iName = "NEW ELEMENT " + presentElements.length;
	var iConfig = "";
	var tID = apwDataManagerGetGlobalVariable("currentTrack");
	var eKey = $("input[name=auth-create-element-elementtypes]:checked").val();

	createFields += iID + "&TrackID=" + tID + "&ElementCatalogKey=" + eKey + "&ElementConfig=" + iConfig + "&ElementName=" + iName;

	$(document).apwManualPostUp({
		'postingDisplayFunction': 'apwManualPostUpPostingDisplayBlank',
		'postingFinishDisplayFunction': 'apwManualPostUpPostingDisplayFinishBlank',
		'postingResponseHandlerFunction': 'createElementAPI',
		'passToken': 'Y',
		'postURL': apiEndpointCreateElement,
		'postFailedFunction': 'createElementAPIFail',
		'postData': createFields
	});
}

function createElementAPI(response) {
	var respObj = $.parseJSON(response);

	if (respObj.status == "ok") {
		var tmpCurElData = respObj.element;

		var elementTotalContainer = $("#element-row-1");

		var nextElContainer = getNextElementColumn();
		//var elementContainer = $(nextElContainer);
		var elementContainer = $(nextElContainer).find("#element-list-output");

		var tmpNewElement = $('<div class="card auth-element-list-item" id="element-list-item-' + tmpCurElData.elementid + '" data-elementid="' + tmpCurElData.elementid + '"><div class="auth-element-icon"><img class="auth-element-icon-image" src="/images/' + tmpCurElData.image + '" /></div><div class="card-content"><span class="card-title cyan-text auth-element-name">' + tmpCurElData.name + '</span></div><div class="card-content"><span class="card-body cyan-text auth-element-typename">' + tmpCurElData.elementtypename + '</span></div><div class="card-action"><a class="blue-grey-text modal-trigger auth-update-element-button" href="#updateelement" data-elementid="' + tmpCurElData.elementid + '"><i class="fa fa-pencil"></i></a><a class="blue-grey-text modal-trigger auth-configure-element-button" href="#configureelement" data-elementid="' + tmpCurElData.elementid + '"><i class="fa fa-cog"></i></a><a class="blue-grey-text modal-trigger auth-port-element-button" href="#portelement" data-elementid="' + tmpCurElData.elementid + '"><i class="fa fa-sign-in"></i></a><a class="blue-grey-text modal-trigger auth-route-element-button" href="#routeelement" data-elementid="' + tmpCurElData.elementid + '"><i class="fa fa-exchange"></i></a><a class="blue-grey-text modal-trigger auth-delete-element-button" href="#deleteelement" data-elementid="' + tmpCurElData.elementid + '"><i class="fa fa-trash"></i></a></div></div>');

		tmpNewElement.data("fullinfo", tmpCurElData);
		//elementContainer.append(tmpNewElement);
		elementContainer.before(tmpNewElement);
		tmpNewElement.find('.modal-trigger').leanModal();

		//If we are not the first element on the screen, add routing from the prior element to us
		var presentElements = $("#element-row-1 div.auth-element-list-item");

		if (presentElements.length > 2) {
			//Make the API call to establish the routing
			var destEl = tmpCurElData.elementid;
			var destTra = apwDataManagerGetGlobalVariable("currentTrack");
			var destIns = apwDataManagerGetGlobalVariable("currentIntegrator");

			var pubEl = $(tmpNewElement).prev(".auth-element-list-item").data("elementid");
			var pubTra = apwDataManagerGetGlobalVariable("currentTrack");
			var pubIns = apwDataManagerGetGlobalVariable("currentIntegrator");

			if (destTra > 0 && destEl != "INVALID") {
				var apiEndpointAddRoute = 'https://iofog.org/api/v1/authoring/element/instance/route/create';

				var updateFields = "PublishingInstanceID=" + pubIns + "&PublishingTrackID=" + pubTra + "&PublishingElementID=" + pubEl + "&DestinationInstanceID=" + destIns + "&DestinationTrackID=" + destTra + "&DestinationElementID=" + destEl;

				$(document).apwManualPostUp({
					'postingDisplayFunction': 'apwManualPostUpPostingDisplayBlank',
					'postingFinishDisplayFunction': 'apwManualPostUpPostingDisplayFinishBlank',
					'postingResponseHandlerFunction': 'addAutomaticRouteAPI',
					'passToken': 'Y',
					'postURL': apiEndpointAddRoute,
					'postFailedFunction': 'addAutomaticRouteAPIFail',
					'postData': updateFields
				});
			}
		}

		//Show the output arrow button
		manageElementOutputHiding();
	}
}

function addAutomaticRouteAPI(response) {
	var respObj = $.parseJSON(response);

	if (respObj.status == "ok") {
		var theRoute = respObj.route;

		//Get the destination element
		var curElement = $("#element-list-output").prev(".auth-element-list-item");

		var fullObject = curElement.data("fullinfo");

		var routingCopy = fullObject.routing;

		//Grab the publishing element (the one before this one)
		var pubElement = $(curElement).prev(".auth-element-list-item");

		var theNewInput = {};
		theNewInput.elementid = pubElement.data("elementid");
		theNewInput.elementname = pubElement.find(".auth-element-name").text();
		theNewInput.elementtypename = pubElement.find(".auth-element-typename").text();

		routingCopy.inputs.intratrack.push(theNewInput);

		fullObject.routing = routingCopy;
		$(curElement).data("fullinfo", fullObject);

		var fullObject3 = pubElement.data("fullinfo");
		var routingCopy3 = fullObject3.routing;

		var theNewOutput = {};
		theNewOutput.elementid = curElement.data("elementid");
		theNewOutput.elementname = curElement.find(".auth-element-name").text();
		theNewOutput.elementtypename = curElement.find(".auth-element-typename").text();

		routingCopy3.outputs.intratrack.push(theNewOutput);

		fullObject3.routing = routingCopy3;
		$(pubElement).data("fullinfo", fullObject3);
	}
}

function clickCreateElement() {
	//Clear the current catalog content so the user sees it is loading
	$("#auth-create-element-catalog-container").empty();

	//Use the currently selected ioIntegrator instance to pull the appropriate catalog
	var iID = apwDataManagerGetGlobalVariable("currentIntegrator");

	var apiEndpointCatalog = 'https://iofog.org/api/v1/authoring/integrator/element/catalog/instanceid/' + iID;

	$(document).apwManualPostUp({
		'postingDisplayFunction': 'apwManualPostUpPostingDisplayBlank',
		'postingFinishDisplayFunction': 'apwManualPostUpPostingDisplayFinishBlank',
		'postingResponseHandlerFunction': 'getCatalog',
		'passToken': 'Y',
		'postURL': apiEndpointCatalog,
		'postFailedFunction': 'getCatalogFail',
		'postData': ''
	});
}

function getCatalog(response) {
	var respObj = $.parseJSON(response);

	if (respObj.status == "ok") {
		var elements = respObj.catalog;
		var catalogContainer = $("#auth-create-element-catalog-container");

		for (var i = 0; i < elements.length; i++) {
			var curElementData = elements[i];
			var tmpCheckedString = "";

			if (i == 0) {
				tmpCheckedString = ' checked="checked"';
			}

			var tmpNewOption = $('<div class="input-field col s4 element-catalog-item"><input name="auth-create-element-elementtypes" type="radio" value="' + curElementData.elementkey + '" id="element-type-' + curElementData.elementkey + '"' + tmpCheckedString + '/><label for="element-type-' + curElementData.elementkey + '"><span class="element-catalog-item-title">' + curElementData.name + '</span><br><span class="element-catalog-item-detail">Category: ' + curElementData.category + '</span><br><span class="element-catalog-item-detail">Publisher: ' + curElementData.publisher + '</span><br><span class="element-catalog-item-detail">Description: ' + curElementData.description + '</span></label></div>');

			catalogContainer.append(tmpNewOption);
		}
	}
}

function confirmDeleteElement() {
	var apiEndpointDeleteElement = 'https://iofog.org/api/v1/authoring/element/instance/delete';

	var deleteFields = "ElementID=";
	var iID = $("#auth-delete-element-message-id").text();

	deleteFields += iID;

	$(document).apwManualPostUp({
		'postingDisplayFunction': 'apwManualPostUpPostingDisplayBlank',
		'postingFinishDisplayFunction': 'apwManualPostUpPostingDisplayFinishBlank',
		'postingResponseHandlerFunction': 'deleteElementAPI',
		'passToken': 'Y',
		'postURL': apiEndpointDeleteElement,
		'postFailedFunction': 'deleteElementAPIFail',
		'postData': deleteFields
	});
}

function deleteElementAPI(response) {
	var respObj = $.parseJSON(response);

	if (respObj.status == "ok") {
		var theElementID = respObj.elementid;

		//Fetch the screen object and update its fields accordingly
		var lookString = "#element-list-item-" + theElementID;
		var curItemFromDOM = $(lookString);

		//Remove the routing for all other elements on the screen regarding this element
		var presentElements = $("#element-row-1 div.auth-element-list-item");
		var ourIndex = 0;

		for (var i = 0; i < presentElements.length; i++) {
			var tmpElement = presentElements[i];
			var tmpElementID = $(tmpElement).data("elementid");

			if (tmpElementID == "BLANK") {
				//Skip this one - it's the hidden anchor
			} else {
				if (tmpElementID == theElementID) {
					ourIndex = i;
				}

				//Get the routing from this element
				var fullObject = $(tmpElement).data("fullinfo");
				var routingCopy = fullObject.routing;
				var outLength = routingCopy.outputs.intratrack.length;
				var inLength = routingCopy.inputs.intratrack.length;
				//console.log("outLength was: " + outLength);
				//console.log("inLength was: " + inLength);
				for (var j = 0; j < outLength; j++) {
					var curRoute = routingCopy.outputs.intratrack[j];

					if (curRoute.elementid == theElementID) {
						//We have a match. Remove this route
						routingCopy.outputs.intratrack.splice(j, 1);
					}
				}

				for (var j = 0; j < inLength; j++) {
					var curRoute = routingCopy.inputs.intratrack[j];

					if (curRoute.elementid == theElementID) {
						//We have a match. Update the name
						routingCopy.inputs.intratrack.splice(j, 1);
					}
				}

				fullObject.routing = routingCopy;
				$(tmpElement).data("fullinfo", fullObject);
			}
		}

		//Rework the routing between the element above and the element below, if valid
		if (ourIndex > 1 && ourIndex < presentElements.length - 1) {
			//Ok - we are not in the first position and not in the last position, which
			//means that we need to tie the two units around us together
			var pubElObj = presentElements[ourIndex - 1];
			var pubElObjID = $(pubElObj).data("elementid");

			var destElObj = presentElements[ourIndex + 1];
			var destElObjID = $(destElObj).data("elementid");

			//Make the API call to establish the routing
			var destEl = destElObjID;
			var destTra = apwDataManagerGetGlobalVariable("currentTrack");
			var destIns = apwDataManagerGetGlobalVariable("currentIntegrator");

			var pubEl = pubElObjID;
			var pubTra = apwDataManagerGetGlobalVariable("currentTrack");
			var pubIns = apwDataManagerGetGlobalVariable("currentIntegrator");

			if (destTra > 0 && destEl != "INVALID") {
				var apiEndpointAddRoute = 'https://iofog.org/api/v1/authoring/element/instance/route/create';

				var updateFields = "PublishingInstanceID=" + pubIns + "&PublishingTrackID=" + pubTra + "&PublishingElementID=" + pubEl + "&DestinationInstanceID=" + destIns + "&DestinationTrackID=" + destTra + "&DestinationElementID=" + destEl;

				apwDataManagerSetGlobalVariable("reroutepublisher", pubEl);
				apwDataManagerSetGlobalVariable("reroutedestination", destEl);

				$(document).apwManualPostUp({
					'postingDisplayFunction': 'apwManualPostUpPostingDisplayBlank',
					'postingFinishDisplayFunction': 'apwManualPostUpPostingDisplayFinishBlank',
					'postingResponseHandlerFunction': 'addAutomaticReRouteAPI',
					'passToken': 'Y',
					'postURL': apiEndpointAddRoute,
					'postFailedFunction': 'addAutomaticReRouteAPIFail',
					'postData': updateFields
				});
			}
		}

		$(curItemFromDOM).remove();

		manageElementOutputHiding();
	}
}

function addAutomaticReRouteAPI(response) {
	var respObj = $.parseJSON(response);

	if (respObj.status == "ok") {
		var theRoute = respObj.route;

		var storedPubElID = apwDataManagerGetGlobalVariable("reroutepublisher");
		var storedDestElID = apwDataManagerGetGlobalVariable("reroutedestination");

		//Get the destination element
		var curElement = $("#element-list-item-" + storedDestElID);

		var fullObject = curElement.data("fullinfo");

		var routingCopy = fullObject.routing;

		//Grab the publishing element (the one before this one)
		var pubElement = $("#element-list-item-" + storedPubElID);

		var theNewInput = {};
		theNewInput.elementid = pubElement.data("elementid");
		theNewInput.elementname = pubElement.find(".auth-element-name").text();
		theNewInput.elementtypename = pubElement.find(".auth-element-typename").text();

		routingCopy.inputs.intratrack.push(theNewInput);

		fullObject.routing = routingCopy;
		$(curElement).data("fullinfo", fullObject);

		var fullObject3 = pubElement.data("fullinfo");
		var routingCopy3 = fullObject3.routing;

		var theNewOutput = {};
		theNewOutput.elementid = curElement.data("elementid");
		theNewOutput.elementname = curElement.find(".auth-element-name").text();
		theNewOutput.elementtypename = curElement.find(".auth-element-typename").text();

		routingCopy3.outputs.intratrack.push(theNewOutput);

		fullObject3.routing = routingCopy3;
		$(pubElement).data("fullinfo", fullObject3);
	}
}

function clickDeleteElement(data) {
	var elementID = data.elementID;

	//Get the current information about the ioIntegrator instance from the object itself
	var lookString = "#element-list-item-" + elementID;
	var curItemFromDOM = $(lookString);

	var curName = "";

	//If this item exists, get the fields
	if (curItemFromDOM.length) {
		curName = $(curItemFromDOM).find(".auth-element-name").text();
	}

	//Put the information into the delete track modal window
	$("#auth-delete-element-message-name").text(curName);
	$("#auth-delete-element-message-id").text(elementID);
}

function confirmDeleteTrack() {
	var apiEndpointDeleteTrack = 'https://iofog.org/api/v1/authoring/integrator/track/delete';

	var deleteFields = "TrackID=";
	var iID = apwDataManagerGetGlobalVariable("currentTrack");

	deleteFields += iID;

	$(document).apwManualPostUp({
		'postingDisplayFunction': 'apwManualPostUpPostingDisplayBlank',
		'postingFinishDisplayFunction': 'apwManualPostUpPostingDisplayFinishBlank',
		'postingResponseHandlerFunction': 'deleteTrackAPI',
		'passToken': 'Y',
		'postURL': apiEndpointDeleteTrack,
		'postFailedFunction': 'deleteTrackAPIFail',
		'postData': deleteFields
	});
}

function deleteTrackAPI(response) {
	var respObj = $.parseJSON(response);

	if (respObj.status == "ok") {
		var theTrackID = respObj.trackid;

		//Fetch the screen object and update its fields accordingly
		var lookString = "#track-list-item-" + theTrackID;
		var curItemFromDOM = $(lookString);

		$(curItemFromDOM).remove();

		//Clear the other information around this integrator
		apwDataManagerSetGlobalVariable("currentTrack", 0);

		clearElementList();
		manageTrackListHiding();
	}
}

function clickDeleteTrack(data) {
	var trackID = data.trackID;

	//Get the current information about the ioIntegrator instance from the object itself
	var lookString = "#track-list-item-" + trackID;
	var curItemFromDOM = $(lookString);

	var curName = "";
	var curDesc = "";

	//If this item exists, get the fields
	if (curItemFromDOM.length) {
		curName = $(curItemFromDOM).find(".auth-track-name").text();
		curDesc = $(curItemFromDOM).find(".auth-track-description").text();
	}

	//Put the information into the delete track modal window
	$("#auth-delete-track-message-name").text(curName);
	$("#auth-delete-track-message-description").text(curDesc);
}

function saveUpdateTrack() {
	var apiEndpointUpdateTrack = 'https://iofog.org/api/v1/authoring/integrator/track/update';

	var updateFields = "TrackID=";
	var iID = apwDataManagerGetGlobalVariable("currentTrack");
	var iName = $("#auth-update-track-trackname").val();
	var iDesc = $("#auth-update-track-trackdescription").val();

	updateFields += iID + "&TrackName=" + iName + "&TrackDescription=" + iDesc;

	$(document).apwManualPostUp({
		'postingDisplayFunction': 'apwManualPostUpPostingDisplayBlank',
		'postingFinishDisplayFunction': 'apwManualPostUpPostingDisplayFinishBlank',
		'postingResponseHandlerFunction': 'updateTrackAPI',
		'passToken': 'Y',
		'postURL': apiEndpointUpdateTrack,
		'postFailedFunction': 'updateTrackAPIFail',
		'postData': updateFields
	});
}

function updateTrackAPI(response) {
	var respObj = $.parseJSON(response);

	if (respObj.status == "ok") {
		var theTrackID = respObj.trackid;

		//Fetch the screen object and update its fields accordingly
		var lookString = "#track-list-item-" + theTrackID;
		var curItemFromDOM = $(lookString);

		//Get the values out of the update form
		var iName = $("#auth-update-track-trackname").val();
		var iDesc = $("#auth-update-track-trackdescription").val();

		$(curItemFromDOM).find(".auth-track-name").text(iName);
		$(curItemFromDOM).find(".auth-track-description").text(iDesc);
	}
}

function clickUpdateTrack(data) {
	var trackID = data.trackID;

	//Get the current information about the ioIntegrator instance from the object itself
	var lookString = "#track-list-item-" + trackID;
	var curItemFromDOM = $(lookString);

	var curName = "";
	var curDesc = "";

	//If this item exists, get the fields
	if (curItemFromDOM.length) {
		curName = $(curItemFromDOM).find(".auth-track-name").text();
		curDesc = $(curItemFromDOM).find(".auth-track-description").text();
	}

	//Put the information into the update integrator modal window
	$("#auth-update-track-trackname").val(curName);
	$("#auth-update-track-trackdescription").val(curDesc);
}

function createNewTrack() {
	var apiEndpointCreateTrack = 'https://iofog.org/api/v1/authoring/integrator/track/create';

	var createFields = "IntegratorInstanceID=";
	var iID = apwDataManagerGetGlobalVariable("currentIntegrator");
	var iName = $("#auth-create-track-trackname").val();
	var iDesc = $("#auth-create-track-trackdescription").val();

	createFields += iID + "&TrackName=" + iName + "&TrackDescription=" + iDesc;

	$(document).apwManualPostUp({
		'postingDisplayFunction': 'apwManualPostUpPostingDisplayBlank',
		'postingFinishDisplayFunction': 'apwManualPostUpPostingDisplayFinishBlank',
		'postingResponseHandlerFunction': 'createTrackAPI',
		'passToken': 'Y',
		'postURL': apiEndpointCreateTrack,
		'postFailedFunction': 'createTrackAPIFail',
		'postData': createFields
	});
}

function createTrackAPI(response) {
	var respObj = $.parseJSON(response);

	if (respObj.status == "ok") {
		var theTrackID = respObj.trackid;
		var iName = $("#auth-create-track-trackname").val();
		var iDesc = $("#auth-create-track-trackdescription").val();

		var trackContainer = $("#tracklist");

		var tmpNewTrack = $('<li class="auth-track-list-item" id="track-list-item-' + theTrackID + '" data-trackid="' + theTrackID + '"><div class="collapsible-header auth-track-name">' + iName + '</div><div class="collapsible-body"><p class="auth-track-description">' + iDesc + '</p><div class="row action"><div class="col s2"><a class="modal-trigger light-green-text auth-update-track-button" href="#updatetrack" data-trackid="' + theTrackID + '"><i class="fa fa-pencil"></i></a></div><div class="col s2"><a class="modal-trigger light-green-text auth-delete-track-button" href="#deletetrack" data-trackid="' + theTrackID + '"><i class="fa fa-trash"></i></a></div></div><!--end row--></div></li>');

		trackContainer.append(tmpNewTrack);

		$('.collapsible').collapsible();
		tmpNewTrack.find('.modal-trigger').leanModal();

		clearCreateTrackForm();

		manageTrackListHiding();
		manageElementOutputHiding();
	}
}

function clearCreateTrackForm() {
	$("#auth-create-track-trackname").val("");
	$("#auth-create-track-trackdescription").val("");
}

function confirmDeleteIntegratorInstance() {
	var apiEndpointDeleteIntegrator = 'https://iofog.org/api/v1/authoring/integrator/instance/delete';

	var deleteFields = "IntegratorInstanceID=";
	var iID = apwDataManagerGetGlobalVariable("currentIntegrator");

	deleteFields += iID;

	$(document).apwManualPostUp({
		'postingDisplayFunction': 'apwManualPostUpPostingDisplayBlank',
		'postingFinishDisplayFunction': 'apwManualPostUpPostingDisplayFinishBlank',
		'postingResponseHandlerFunction': 'deleteIntegratorAPI',
		'passToken': 'Y',
		'postURL': apiEndpointDeleteIntegrator,
		'postFailedFunction': 'deleteIntegratorAPIFaile',
		'postData': deleteFields
	});
}

function deleteIntegratorAPI(response) {
	var respObj = $.parseJSON(response);

	if (respObj.status == "ok") {
		var theInstanceID = respObj.instanceid;

		//Fetch the screen object and update its fields accordingly
		var lookString = "#instance-list-item-" + theInstanceID;
		var curItemFromDOM = $(lookString);

		$(curItemFromDOM).remove();

		//Clear the other information around this integrator
		apwDataManagerSetGlobalVariable("currentIntegrator", "");
		apwDataManagerSetGlobalVariable("currentTrack", 0);
		apwDataManagerSetGlobalVariable("currentStreamViewerURL", "");
		apwDataManagerSetGlobalVariable("currentStreamViewerToken", "");
		apwDataManagerSetGlobalVariable("currentConsoleURL", "");
		apwDataManagerSetGlobalVariable("currentConsoleToken", "");

		clearTrackList();
		clearElementList();
		manageTrackListHiding();
		manageIntegratorListHiding();
		manageElementOutputHiding();
	}
}

function clickDeleteIntegrator(data) {
	var instanceID = data.instanceID;

	//Get the current information about the ioIntegrator instance from the object itself
	var lookString = "#instance-list-item-" + instanceID;
	var curItemFromDOM = $(lookString);

	var curName = "";

	//If this item exists, get the fields
	if (curItemFromDOM.length) {
		curName = $(curItemFromDOM).find(".auth-integrator-name").text();
	}

	//Put the information into the update integrator modal window
	$("#auth-delete-integrator-message-name").text(curName);
	$("#auth-delete-integrator-message-id").text(instanceID);
}

function saveUpdateIntegratorInstance() {
	var apiEndpointUpdateIntegrator = 'https://iofog.org/api/v1/authoring/integrator/instance/update';

	var updateFields = "IntegratorInstanceID=";
	var iID = apwDataManagerGetGlobalVariable("currentIntegrator");
	var iName = $("#auth-update-integrator-integratorname").val();
	var iDesc = $("#auth-update-integrator-integratordescription").val();
	var iLoc = $("#auth-update-integrator-integratorlocation").val();

	updateFields += iID + "&IntegratorName=" + iName + "&IntegratorDescription=" + iDesc + "&IntegratorLocation=" + iLoc;

	$(document).apwManualPostUp({
		'postingDisplayFunction': 'apwManualPostUpPostingDisplayBlank',
		'postingFinishDisplayFunction': 'apwManualPostUpPostingDisplayFinishBlank',
		'postingResponseHandlerFunction': 'updateIntegratorAPI',
		'passToken': 'Y',
		'postURL': apiEndpointUpdateIntegrator,
		'postFailedFunction': 'updateIntegratorAPIFail',
		'postData': updateFields
	});
}

function updateIntegratorAPI(response) {
	var respObj = $.parseJSON(response);

	if (respObj.status == "ok") {
		var theInstanceID = respObj.instanceid;

		//Fetch the screen object and update its fields accordingly
		var lookString = "#instance-list-item-" + theInstanceID;
		var curItemFromDOM = $(lookString);

		//Get the values out of the update form
		var iName = $("#auth-update-integrator-integratorname").val();
		var iDesc = $("#auth-update-integrator-integratordescription").val();
		var iLoc = $("#auth-update-integrator-integratorlocation").val();

		$(curItemFromDOM).find(".auth-integrator-name").text(iName);
		$(curItemFromDOM).find(".auth-integrator-description").text(iDesc);
		$(curItemFromDOM).find(".auth-integrator-location").text(iLoc);
	}
}

function clickUpdateIntegrator(data) {
	var instanceID = data.instanceID;

	//Get the current information about the ioIntegrator instance from the object itself
	var lookString = "#instance-list-item-" + instanceID;
	var curItemFromDOM = $(lookString);

	var curName = "";
	var curDesc = "";
	var curLoc = "";

	//If this item exists, get the fields
	if (curItemFromDOM.length) {
		curName = $(curItemFromDOM).find(".auth-integrator-name").text();
		curDesc = $(curItemFromDOM).find(".auth-integrator-description").text();
		curLoc = $(curItemFromDOM).find(".auth-integrator-location").text();
	}

	//Put the information into the update integrator modal window
	$("#auth-update-integrator-integratorname").val(curName);
	$("#auth-update-integrator-integratordescription").val(curDesc);
	$("#auth-update-integrator-integratorlocation").val(curLoc);
}

function createNewIntegratorInstance() {
	var apiEndpointCreateIntegrator = 'https://iofog.org/api/v1/authoring/integrator/instance/create';

	var createFields = "IntegratorType=";
	var iType = $("input[name=auth-create-integrator-integratortypes]").val();
	var iName = $("#auth-create-integrator-integratorname").val();
	var iDesc = $("#auth-create-integrator-integratordescription").val();
	var iLoc = $("#auth-create-integrator-integratorlocation").val();

	createFields += iType + "&IntegratorName=" + iName + "&IntegratorDescription=" + iDesc + "&IntegratorLocation=" + iLoc;

	$(document).apwManualPostUp({
		'postingDisplayFunction': 'apwManualPostUpPostingDisplayBlank',
		'postingFinishDisplayFunction': 'apwManualPostUpPostingDisplayFinishBlank',
		'postingResponseHandlerFunction': 'createIntegratorAPI',
		'passToken': 'Y',
		'postURL': apiEndpointCreateIntegrator,
		'postFailedFunction': 'createIntegratorAPIFail',
		'postData': createFields
	});

	clearCreateIntegratorForm();
}

function createIntegratorAPI(response) {
	var respObj = $.parseJSON(response);

	if (respObj.status == "ok") {
		var theInstanceObj = respObj.instance;

		var instanceContainer = $("#integratorlist");

		var milTime = theInstanceObj.lastactive * 1000;
		var lastActiveString = "";

		if (milTime > 0) {
			var t = new Date(milTime);
			lastActiveString = t.getMonth() + 1 + "-" + t.getDate() + "-" + t.getFullYear() + " at " + t.getHours() + ":" + t.getMinutes() + ":" + t.getSeconds();
		} else {
			lastActiveString = "Never";
		}

		var tmpNewInstance = $('<li class="auth-integrator-list-item" id="instance-list-item-' + theInstanceObj.id + '" data-instanceid="' + theInstanceObj.id + '"><div class="collapsible-header auth-integrator-name">' + theInstanceObj.name + '</div><div class="collapsible-body"><p class="integrator-details">Local IP address:<br><span class="auth-integrator-localip">' + theInstanceObj.localip + '</span></p><p class="integrator-details">Status:<br><span class="auth-integrator-status">' + theInstanceObj.status + '</span></p><p class="integrator-details">Last active:<br><span class="auth-integrator-lastactive">' + lastActiveString + '</span></p><p class="integrator-details">Description:<br><span class="auth-integrator-description">' + theInstanceObj.description + '</span></p><p class="integrator-details">Location:<br><span class="auth-integrator-location">' + theInstanceObj.location + '</span></p><!--edit/delete buttons--><div class="row action"><div class="col s2"><a class="modal-trigger deep-purple-text auth-update-integrator-instance-button" href="#updateinstance" data-instanceid="' + theInstanceObj.id + '"><i class="fa fa-pencil"></i></a></div><div class="col s2"><a class="modal-trigger deep-purple-text auth-delete-integrator-instance-button" href="#deleteintegrator" data-instanceid="' + theInstanceObj.id + '"><i class="fa fa-trash"></i></a></div><div class="col s2"><a class="modal-trigger deep-purple-text auth-provisioning-key-button" href="#provisioning" data-instanceid="' + theInstanceObj.id + '"><i class="fa fa-key"></i></a></div></div><!--end row--></div><!--end collapsible body--></li>');

		instanceContainer.append(tmpNewInstance);

		$('.collapsible').collapsible();
		tmpNewInstance.find('.modal-trigger').leanModal();

		manageTrackListHiding();
		manageIntegratorListHiding();
		manageElementOutputHiding();
	}
}

function clearCreateIntegratorForm() {
	$("#auth-create-integrator-integratorname").val("");
	$("#auth-create-integrator-integratordescription").val("");
	$("#auth-create-integrator-integratorlocation").val("");
}

function clickProvisioningKey(data) {
	//Clear any existing provisioning key
	$("#auth-provisioning-key-text").empty();

	var instanceID = data.instanceID;

	var apiEndpointProvKey = 'https://iofog.org/api/v1/authoring/integrator/provisioningkey/instanceid/' + instanceID;

	$(document).apwManualPostUp({
		'postingDisplayFunction': 'apwManualPostUpPostingDisplayBlank',
		'postingFinishDisplayFunction': 'apwManualPostUpPostingDisplayFinishBlank',
		'postingResponseHandlerFunction': 'getProvisioningKey',
		'passToken': 'Y',
		'postURL': apiEndpointProvKey,
		'postFailedFunction': 'getProvisioningKeyFail',
		'postData': ''
	});
}

function getProvisioningKey(response) {
	var respObj = $.parseJSON(response);

	if (respObj.status == "ok") {
		var theKey = respObj.provisioningkey;

		$("#auth-provisioning-key-text").html(theKey);
	}
}

function clickTrack(data) {
	var lastTrackID = apwDataManagerGetGlobalVariable("currentTrack");
	var clickTrackID = data.trackID;

	if (lastTrackID == clickTrackID) {
		//Don't change anything
	} else {
		//Set the visuals on the list
		setActiveTrackVisuals(clickTrackID);

		//Set this track as the current one
		apwDataManagerSetGlobalVariable("currentTrack", clickTrackID);

		//Clear the list of elements because the new set is about to load
		clearElementList();

		//Load the elements and display them
		var apiEndpointElements = 'https://iofog.org/api/v1/authoring/integrator/track/element/list/trackid/' + clickTrackID;

		$(document).apwManualPostUp({
			'postingDisplayFunction': 'apwManualPostUpPostingDisplayBlank',
			'postingFinishDisplayFunction': 'apwManualPostUpPostingDisplayFinishBlank',
			'postingResponseHandlerFunction': 'getElementList',
			'passToken': 'Y',
			'postURL': apiEndpointElements,
			'postFailedFunction': 'getElementListFail',
			'postData': ''
		});
	}
}

function getNextElementColumn() {
	//This function just checks to see which element column is the first one to have fewer than the others
	//We return that column name as a string to allow for easy placement.
	//NOTE: this method will result in gaps being filled... but will not allow for intelligent shifting or re-balancing

	//UPDATE 12-2-2015 by KPH
	//Mask this functionality and hard code a return of 1
	//This is so we display elements under each other for right now - it coordinates with wider elements for a Rev 2 build

	/*
 //Get all of the element counts first
 var els1 = $("#element-col-1 div.auth-element-list-item:not(#element-list-item-BLANK)");
 var c1 = els1.length;
 
 var els2 = $("#element-col-2 div.auth-element-list-item");
 var c2 = els2.length;
 
 var els3 = $("#element-col-3 div.auth-element-list-item");
 var c3 = els3.length;
 
 var els4 = $("#element-col-4 div.auth-element-list-item");
 var c4 = els4.length;
 
 //Find the lowest number
 var lowest = 1000;
 
 if(c1 < lowest)
 {
 	lowest = c1;
 }
 
 if(c2 < lowest)
 {
 	lowest = c2;
 }
 
 if(c3 < lowest)
 {
 	lowest = c3;
 }
 
 if(c4 < lowest)
 {
 	lowest = c4;
 }
 
 //Now find the first lowest number
 if(c1 == lowest)
 {
 	return "#element-col-1";
 }
 else if(c2 == lowest)
 {
 	return "#element-col-2";
 }
 else if(c3 == lowest)
 {
 	return "#element-col-3";
 }
 else
 {
 	return "#element-col-4";
 }
 */

	return "#element-col-1";
}

function getElementList(response) {
	var respObj = $.parseJSON(response);

	if (respObj.status == "ok") {
		var elements = respObj.elements;

		var elementTotalContainer = $("#element-row-1");

		for (var i = 0; i < elements.length; i++) {
			var nextElContainer = getNextElementColumn();
			//var elementContainer = $(nextElContainer);
			var elementContainer = $(nextElContainer).find("#element-list-output");

			var tmpCurElData = elements[i];

			var tmpNewElement = $('<div class="card auth-element-list-item" id="element-list-item-' + tmpCurElData.elementid + '" data-elementid="' + tmpCurElData.elementid + '"><div class="auth-element-icon"><img class="auth-element-icon-image" src="/images/' + tmpCurElData.image + '" /></div><div class="card-content"><span class="card-title cyan-text auth-element-name">' + tmpCurElData.name + '</span></div><div class="card-content"><span class="card-body cyan-text auth-element-typename">' + tmpCurElData.elementtypename + '</span></div><div class="card-action"><a class="blue-grey-text modal-trigger auth-update-element-button" href="#updateelement" data-elementid="' + tmpCurElData.elementid + '"><i class="fa fa-pencil"></i></a><a class="blue-grey-text modal-trigger auth-configure-element-button" href="#configureelement" data-elementid="' + tmpCurElData.elementid + '"><i class="fa fa-cog"></i></a><a class="blue-grey-text modal-trigger auth-port-element-button" href="#portelement" data-elementid="' + tmpCurElData.elementid + '"><i class="fa fa-sign-in"></i></a><a class="blue-grey-text modal-trigger auth-route-element-button" href="#routeelement" data-elementid="' + tmpCurElData.elementid + '"><i class="fa fa-exchange"></i></a><a class="blue-grey-text modal-trigger auth-delete-element-button" href="#deleteelement" data-elementid="' + tmpCurElData.elementid + '"><i class="fa fa-trash"></i></a></div></div>');

			tmpNewElement.data("fullinfo", tmpCurElData);
			//elementContainer.append(tmpNewElement);
			elementContainer.before(tmpNewElement);

			tmpNewElement.find('.modal-trigger').leanModal();

			//var tmpNewElementButton = $('<div class="new-element auth-element-list-add-item" id="element-list-add-item-' + tmpCurElData.elementid + '" data-elementaboveid="' + tmpCurElData.elementid + '" data-elementbelowid="' + tmpCurElData.elementid + '"><a class="modal-trigger cyan-text" href="#createelement"><i class="fa fa-plus-circle fa-2x"></i></a></div>');

			//elementContainer.append(tmpNewElementButton);
		}

		//elementTotalContainer.find('.modal-trigger:not(#auth-element-main-add-button)').leanModal();

		//Set the add element button to active
		$("#auth-element-main-add-button").removeClass("disabled");
		$("#auth-element-main-add-button").attr("href", "#createelement");

		//Show the output arrow button if there are any elements present
		manageElementOutputHiding();
	}
}

function setActiveIntegratorVisuals(clickInstanceID) {
	var presentintegrators = $("#integratorlist li.auth-integrator-list-item");

	for (var i = 0; i < presentintegrators.length; i++) {
		var curIntegrator = $(presentintegrators[i]);
		var curIntegratorID = curIntegrator.data("instanceid");
		if (curIntegratorID == clickInstanceID) {
			curIntegrator.find("div.collapsible-header").addClass("integratoractive");
		} else {
			curIntegrator.find("div.collapsible-header").removeClass("integratoractive");
		}
	}
}

function setActiveTrackVisuals(clickTrackID) {
	var presentTracks = $("#tracklist li.auth-track-list-item");

	for (var i = 0; i < presentTracks.length; i++) {
		var curTrack = $(presentTracks[i]);
		var curTrackID = curTrack.data("trackid");
		if (curTrackID == clickTrackID) {
			curTrack.find("div.collapsible-header").addClass("trackactive");
		} else {
			curTrack.find("div.collapsible-header").removeClass("trackactive");
		}
	}
}

function clickIntegratorInstance(data) {
	var lastInstanceID = apwDataManagerGetGlobalVariable("currentIntegrator");
	var clickInstanceID = data.instanceID;

	if (lastInstanceID == clickInstanceID) {
		//Don't change anything
	} else {
		//Change the visuals to show this one highlighted
		setActiveIntegratorVisuals(clickInstanceID);

		//Set this integrator instance as the current one
		apwDataManagerSetGlobalVariable("currentIntegrator", clickInstanceID);

		//Clear the list of tracks because the new one is about to load
		clearTrackList();

		//Clear the currently selected track because we just loaded the list. None are selected.
		apwDataManagerSetGlobalVariable("currentTrack", 0);

		//Clear the ioElement list because we are not displaying the details of any track yet.
		clearElementList();

		//Load the tracks for this integrator instance and display them
		var apiEndpointTracks = 'https://iofog.org/api/v1/authoring/integrator/track/list/instanceid/' + clickInstanceID;

		$(document).apwManualPostUp({
			'postingDisplayFunction': 'apwManualPostUpPostingDisplayBlank',
			'postingFinishDisplayFunction': 'apwManualPostUpPostingDisplayFinishBlank',
			'postingResponseHandlerFunction': 'getTrackList',
			'passToken': 'Y',
			'postURL': apiEndpointTracks,
			'postFailedFunction': 'getTrackListFail',
			'postData': ''
		});

		//Get the Stream Viewer and Debug Console API URLs for this integrator instance and
		//store them in the proper global variables
		var apiEndpoint = 'https://iofog.org/api/v1/authoring/integrator/viewer/access/instanceid/' + clickInstanceID;

		$(document).apwManualPostUp({
			'postingDisplayFunction': 'apwManualPostUpPostingDisplayBlank',
			'postingFinishDisplayFunction': 'apwManualPostUpPostingDisplayFinishBlank',
			'postingResponseHandlerFunction': 'getDebugToolsURLs',
			'passToken': 'Y',
			'postURL': apiEndpoint,
			'postFailedFunction': 'getDebugToolURLsFail',
			'postData': ''
		});
	}
}

function clearTrackList() {
	var presentTracks = $("#tracklist li.auth-track-list-item");

	for (var i = 0; i < presentTracks.length; i++) {
		var tmpTrack = presentTracks[i];
		var tmpTrackID = $(tmpTrack).data("trackid");

		if (tmpTrackID == 0) {
			//Skip this one - it's the hidden anchor track
		} else {
			$(tmpTrack).remove();
		}
	}

	//Set the add track button to active
	$("#auth-track-main-add-button").addClass("disabled");
	$("#auth-track-main-add-button").attr("href", "#nointegrator");

	manageTrackListHiding();
	manageElementOutputHiding();
}

function manageElementOutputHiding() {
	var presentElements = $("#element-row-1 div.auth-element-list-item");

	if (presentElements.length == 1) {
		$("#element-list-output").addClass("devisualed");
	} else {
		$("#element-list-output").removeClass("devisualed");
	}
}

function manageTrackListHiding() {
	var presentTracks = $("#tracklist li.auth-track-list-item");

	if (presentTracks.length == 1) {
		$("#tracklist").addClass("devisualed");
	} else {
		$("#tracklist").removeClass("devisualed");
	}
}

function manageIntegratorListHiding() {
	var presentintegrators = $("#integratorlist li.auth-integrator-list-item");

	if (presentintegrators.length == 1) {
		$("#integratorlist").addClass("devisualed");
	} else {
		$("#integratorlist").removeClass("devisualed");
	}
}

function clearElementList() {
	var presentElements = $("#element-row-1 div.auth-element-list-item");
	var presentAddButtons = $("#element-row-1 div.auth-element-list-add-item");

	for (var i = 0; i < presentElements.length; i++) {
		var tmpElement = presentElements[i];
		var tmpElementID = $(tmpElement).data("elementid");

		if (tmpElementID == "BLANK") {
			//Skip this one - it's the hidden anchor
		} else {
			$(tmpElement).remove();
		}
	}

	for (var i = 0; i < presentAddButtons.length; i++) {
		var tmpButton = presentAddButtons[i];
		var tmpButtonAboveID = $(tmpButton).data("elementaboveid");
		var tmpButtonBelowID = $(tmpButton).data("elementbelowid");

		if (tmpButtonAboveID == "BLANK" && tmpButtonBelowID == "BLANK") {
			//Skip this one - it's the hidden anchor
		} else {
			$(tmpButton).remove();
		}
	}

	//Set the add element button to disabled
	$("#auth-element-main-add-button").addClass("disabled");
	$("#auth-element-main-add-button").attr("href", "#notrack");

	//Hide the output arrow button
	manageElementOutputHiding();
}

function getTrackList(response) {
	var respObj = $.parseJSON(response);

	if (respObj.status == "ok") {
		var tracks = respObj.tracks;
		var trackContainer = $("#tracklist");

		for (var i = 0; i < tracks.length; i++) {
			var tmpCurTrackData = tracks[i];

			var tmpNewTrack = $('<li class="auth-track-list-item" id="track-list-item-' + tmpCurTrackData.id + '" data-trackid="' + tmpCurTrackData.id + '"><div class="collapsible-header auth-track-name">' + tmpCurTrackData.name + '</div><div class="collapsible-body"><p class="auth-track-description">' + tmpCurTrackData.description + '</p><div class="row action"><div class="col s2"><a class="modal-trigger light-green-text auth-update-track-button" href="#updatetrack" data-trackid="' + tmpCurTrackData.id + '"><i class="fa fa-pencil"></i></a></div><div class="col s2"><a class="modal-trigger light-green-text auth-delete-track-button" href="#deletetrack" data-trackid="' + tmpCurTrackData.id + '"><i class="fa fa-trash"></i></a></div></div><!--end row--></div></li>');

			trackContainer.append(tmpNewTrack);
		}

		$('.collapsible').collapsible();
		trackContainer.find('.modal-trigger').leanModal();

		//Set the add track button to active
		$("#auth-track-main-add-button").removeClass("disabled");
		$("#auth-track-main-add-button").attr("href", "#createtrack");

		manageTrackListHiding();
		manageElementOutputHiding();
	}
}

function getDebugToolsURLs(response) {
	var respObj = $.parseJSON(response);

	if (respObj.status == "ok") {
		var accessInfo = respObj.access;

		apwDataManagerSetGlobalVariable("currentStreamViewerURL", accessInfo.streamviewerurl);
		apwDataManagerSetGlobalVariable("currentStreamViewerToken", accessInfo.streamviewertoken);
		apwDataManagerSetGlobalVariable("currentConsoleURL", accessInfo.consoleurl);
		apwDataManagerSetGlobalVariable("currentConsoleToken", accessInfo.consoletoken);
	}
}

function getIntegratorList() {
	$(document).apwManualPostUp({
		'postingDisplayFunction': 'apwManualPostUpPostingDisplayBlank',
		'postingFinishDisplayFunction': 'apwManualPostUpPostingDisplayFinishBlank',
		'postingResponseHandlerFunction': 'refreshIntegratorList',
		'passToken': 'Y',
		'postURL': 'https://iofog.org/api/v1/authoring/integrator/instances/list',
		'postFailedFunction': 'refreshIntegratorListFail',
		'postData': ''
	});
}

function refreshIntegratorList(response) {
	//Loop through the list of integrators (if any)
	//and update the data fields on the screen.
	//
	//NOTE: at this time we are skipping the addition or removal of integrators
	//via this background thread.
	//
	var respObj = $.parseJSON(response);

	if (respObj.status == "ok") {
		var integratorList = respObj.instances;

		for (var i = 0; i < integratorList.length; i++) {
			var tmpIntegrator = integratorList[i];

			//See if we can find this particular integrator
			var lookString = "#instance-list-item-" + tmpIntegrator.id;
			var curItemFromDOM = $(lookString);

			var milTime = tmpIntegrator.lastactive * 1000;
			var lastActiveString = "";

			if (milTime > 0) {
				var t = new Date(milTime);
				var minutes = t.getMinutes();

				var minString = "";

				if (minutes < 10) {
					minString = "0" + minutes;
				} else {
					minString = minutes;
				}

				var seconds = t.getSeconds();

				var secString = "";

				if (seconds < 10) {
					secString = "0" + seconds;
				} else {
					secString = seconds;
				}

				lastActiveString = t.getMonth() + 1 + "-" + t.getDate() + "-" + t.getFullYear() + " at " + t.getHours() + ":" + minString + ":" + secString;
			} else {
				lastActiveString = "Never";
			}

			//If this item exists, update the fields
			if (curItemFromDOM.length) {
				$(curItemFromDOM).find(".auth-integrator-localip").html(tmpIntegrator.localip);
				$(curItemFromDOM).find(".auth-integrator-status").html(tmpIntegrator.status);
				$(curItemFromDOM).find(".auth-integrator-lastactive").html(lastActiveString);
			}
		}
	} else {
		//NOTE: This will crash JavaScript in IE < 10 because of the console.log call
		console.log("ERROR: The response was not 'ok' from the server on getting the integrator list.");
	}
}