// =========================================================================
//
// inhibit.js - Provide functions to extend MIT Simile's Exhibit HTML to
//              throttle data sets by query so they don't overwhelm Exhibit.
//
// version 1.0, 12 February 2008
// David Wood (david at http://zepheira.com/)
//
// =========================================================================
//
// Copyright (C) 2008 Zepheira, LLC (http://zepheira.com)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// =========================================================================
//
// Design Notes:
//
// This library works with an Active PURL to "negotiate" the number of query
// results from a Web service until the number of results is less than
// exhibitMaxCount, then an Exhibit is built to handle the results.
// There are four steps:
// 1) HTTP HEAD on <URL> to see if it is an Active PURL.
// 2) HTTP GET on <PURL> to get the query parameters
// (used to build an HTML query UI).
// NB: In this version, an HTML fragment is returned from the Active PURL.
// TODO: Handle XML from the Active PURL and perform XSLT in the client.  See:
// http://johannburkard.de/blog/programming/javascript/xslt-js-version-3-0-released-xml-xslt-jquery-plugin.html
// 3) HTTP HEAD on <PURL> with query string input to get a count of the results.
//    When the count is less than exhibitMaxCount, proceed to Step 4.
// 4) HTTP GET on <PURL> to be redirected to the Web service for final query.
// =========================================================================

// Avoid Mozilla/Firefox "same origin" policy for some servers.
//document.domain = "zepheira.com";

// Document globals
var dataURL;  // The URL of the Web service providing data to load into Exhibit.
var countURL; // The dataURL with a query string of parameters as defined by the user.
var exhibitMaxCount = 1000;

// Executed on document load.
// NB: Can't use JQuery's $(document).ready() here because it is in an external script.
window.onload = function(){
// # (1a)
	
	// Get the data URL.
	dataURL = document.getElementById("inhibitdata").href;

	// Retrieve query metadata from the URL, build and display the query form.
	if ( dataURL != null ) {
		checkIfActivePURL();
	} else {
		alert ("No data URL found.  Nothing to do.");
	}
}

// Check the URL to see if is an Active PURL.
function checkIfActivePURL() {
// # (1b)
	
	// Check the HEAD response from the URL to see if
	// it contains a PURL header and, if so, whether it is an Active PURL.
	ajaxCaller.head(dataURL, null, onCheckIsActivePURLResponse, false, "checkIsActivePURL");

}

// Callback for checking whether a URL is an Active PURL.
function onCheckIsActivePURLResponse (message, headers, callingContext) {
// # (1c)
	
	if ( headers["X-Purl"] && headers["X-Purl"].indexOf("(Active)") > -1 ) {
		
		// Build a query interface for the PURL's Web service.
		getQueryMetadata();		
	} else {
		alert("The URL " + dataURL + " is not an Active PURL.  It cannot be used with Inhibit.");
		reportHeaders();
	}
}

// Gets HTML representing a query interface for a PURL.
function getQueryMetadata() {
// # (2a)
	// GET its query metadata by retrieving <URL>.
	// The query metadata should be in XML.  Run it through
	// the inhibit.xsl transformation to build an HTML
	// fragment representing a query interface.
	// NB: Safari does not support in-browser XSLT calls
	// from Javascript :(
	// (http://developer.apple.com/internet/safari/faq.html#anchor21)
	// Either call a Web service to do the transformation or have
	// the Active PURL optionally return HTML fragments...
	signalLoadingResults();
	ajaxCaller.get(dataURL, null, onGetQueryMetadataResponse, false, "getQueryMetadata");
}

// Callback for getting a metadata form from the Active PURL.
function onGetQueryMetadataResponse (message, headers, callingContext) {
// # (2b)
	
	// Make sure we only accept the expected HTML fragment.
	if ( message.length > 0 ) {

		document.getElementById("inhibit-query").innerHTML = message;
		
	} else {
		// Throw an error.
		alert("Error: Bad content received.  Aborting." + "  Content-Type: " + headers["Content-Type"]);
		// DBG
		var report;
		for (key in headers) {
			report += "[" + key + "] -&gt; [" + headers[key] + "]<br/>";
		}
		document.getElementById("inhibit-query").innerHTML += report;
	}
	setVisibility("inhibit-query", "inline");
}

// Submits a query and gets a count of results.
function getCount() {
// # (3a)
	// Create the appropriate query string from the form elements.
	countURL = dataURL + "?";
	
	jQuery('.active_purl').each(function(index, element) {
		var id = jQuery(this).attr('id');
		var value = jQuery(this).val();
		countURL += escape(id) + "=" + escape(value);
	});
	
	ajaxCaller.head(countURL, null, onGetCountResponse, false, "getCount");
}

// Callback for getting a count of query results.
function onGetCountResponse (message, headers, callingContext) {
// # (3b)
	
	if ( headers["X-Purl-Count"] ) {
		if ( headers["X-Purl-Count"] <= exhibitMaxCount ) {
			// # (4)
			
			// Load Exhibit.  Thanks to David Huynh for this invocation.
			var fDone = function() {
		      window.exhibit = Exhibit.create();
		      window.exhibit.configureFromDOM();
			};
		   	window.database = Exhibit.Database.create();
			// Load the data URL into Exhibit.
		   	window.database._loadLinks(
		      [ countURL ],
		      fDone
		   	);
			
			// Hide the Inhibit divs.
			setVisibility("inhibit-count", "none");
			setVisibility("inhibit-query", "none");
		} else {
			// Show the count and leave the form so the query may be modified.
			document.getElementById("inhibit-count").innerHTML = "The current query results in " + headers["X-Purl-Count"] + " records, which is too large to display in Exhibit.  Please refine your query until the results are less than " + exhibitMaxCount;
			setVisibility("inhibit-count", "inline");
			setVisibility("inhibit-query", "inline");
		}
	} else {
		// Throw an error.
		alert("Error: Bad content received.  Aborting.");
		// DBG
		reportHeaders();
	}	
}

/*
 * Utility Methods
 */
// Sets the visibility of an HTML element.
function setVisibility(id, visibility) {
	document.getElementById(id).style.display = visibility;
}

function signalLoadingResults() {
	document.getElementById("inhibit-query").innerHTML = "<p>Loading ...<\/p>";
}

function reportHeaders() {
	var report;
	for (key in headers) {
		report += "[" + key + "] -&gt; [" + headers[key] + "]<br/>";
	}
	document.getElementById("inhibit-query").innerHTML += report;
	setVisibility("inhibit-query", "inline");
}

