/*
 * Rhizomer AJAX
 *
 * Author: http://rhizomik.net/~roberto
 */
 
var rhizomik;
if (rhizomik && (typeof rhizomik != "object" || rhizomik.NAME))
    throw new Error("Namespace 'rhizomik' already exists");
rhizomik = {};
rhizomik.NAME = "Rhizomik";
rhizomik.VERSION = 1.0;

/****************************************************************************
 * Rhizomer Class
 ****************************************************************************/
rhizomik.Rhizomer = function(baseURL, targetElem, defaultQuery)
{
	var self = this;

	/**
	 * Private Attributes
	 */	
	// Base URL for Ajax connections and styles
	var base = baseURL || "http://localhost:8080/rhizomer";
	// Target element for result HTML
	var target = targetElem || document.getElementById("metadata");
	// XSL transformation engine
	var transform = new rhizomik.Transform(base);
	// Wait image
	var waitImage = "<img id='waitImage' src='"+baseURL+"/images/black-loader.gif'/>";
	
	// Last history step
	var last = null;
	
	initialiseHistory(defaultQuery);
	
	/**
	 * Private Methods
	 */
	// Default XMLHTTPRequest on failure function
	function onFailure(o)
	{
		mySimpleDialog = new YAHOO.widget.SimpleDialog("dlg", { 
			width: "20em", 
			fixedcenter:true,
			modal:true,
		    visible:false,
			draggable:false });
		mySimpleDialog.setHeader("Error "+o.statusText);
		mySimpleDialog.setBody(o.responseText);
		mySimpleDialog.cfg.setProperty("icon",YAHOO.widget.SimpleDialog.ICON_WARN);
	};
	// XMLHTTPRequest GET
	function get(url, callback)
	{
		var oCallback = {
				success: function(o) { callback(o.responseText); },
				failure: function(o) { onFailure(o); }
			};
		YAHOO.util.Connect.setDefaultPostHeader(false);
		YAHOO.util.Connect.initHeader('Accept', 'application/rdf+xml');
		YAHOO.util.Connect.asyncRequest('GET', url, oCallback);
	};
	// XMLHTTPRequest PUT
	function put(url, uri, content, contenttype, callback)
	{
		var oCallback = {
				success: function(o) { callback(o.responseText); },
				failure: function(o) { onFailure(o); }
			};
		YAHOO.util.Connect.setDefaultPostHeader(false);
		YAHOO.util.Connect.initHeader('Content-Type', contenttype);
		YAHOO.util.Connect.asyncRequest('PUT', url+'?uri='+uri, oCallback, content);
	};
	// XMLHTTPRequest POST
	function post(url, content, contenttype, callback)
	{
		var oCallback = {
				success: function(o) { callback(o.responseText); },
				failure: function(o) { onFailure(o); }
			};
		YAHOO.util.Connect.setDefaultPostHeader(false);
		YAHOO.util.Connect.initHeader('Content-Type', contenttype);
		YAHOO.util.Connect.asyncRequest('POST', url, oCallback, content);
	} ;
	// XMLHTTPRequest DELETE
	function del(url, uri, callback)
	{
		var oCallback = {
				success: function(o) { callback(o.responseText); },
				failure: function(o) { onFailure(o); }
			};
		YAHOO.util.Connect.asyncRequest('DELETE', url+'?uri='+uri, oCallback);
	};
	
	// By default, on successful query add response to history
	function defaultOnResponse(query, response)
	{
		dhtmlHistory.add("history"+hex_md5(query), {query: query, response: response});
	};
	// Send query and add result to history
	function query(expression, callback)
	{
		get(base + "?query="+expression, 
			function(out) {defaultOnResponse(expression, out); callback(out);});
	};
	// Send query but do not add it to history
	function queryNoHistory(expression, callback)
	{
		get(base + "?query="+expression, 
			function(out) {callback(out);});
	};
	// Handle history change (back and forward) and reloads.
	// When there is not history data, issue the default query
	function handleHistoryChange(newLocation, historyData)
	{
		if (historyData)
		{
			last = historyData;
			transform.rdf2html(historyData.response, target);
		}
		else // Issue default query
		{
			get(base + "?query="+defaultQuery,
				function(out) {transform.rdf2html(out, target);});
		}
	};
	// Initialise history, then detect and manage first load or reload
	function initialiseHistory(defaultQuery)
	{
		dhtmlHistory.initialize();
		dhtmlHistory.addListener(handleHistoryChange);

		// Issue default query for first load
		if (dhtmlHistory.isFirstLoad())
		{
			get(base + "?query="+defaultQuery,
				function(out) {transform.rdf2html(out, target);});
		}
		else // It is a reload, reissue the last query
		{
			if (last!=null)
				query(last.query, function(out) {transform.rdf2html(out, target);});
		}
	};
		
	/**
	 * Public Methods
	 */
	// Show message in the target element area
	self.getBaseURL = function()
	{
		return base;
	};
	// Show message in the target element area
	self.showMessage = function(message)
	{
		target.innerHTML = message;
	};
	// Perform SPARQL query and return RDF/XML to the provided callback function
	self.sparqlRDF = function(sparqlQuery, callback)
	{
		queryNoHistory(encodeURIComponent(sparqlQuery),
			function(out) {callback(out);});
	};
	// Perform SPARQL query and return HTML is specified target DOM element.
	// Intended for rendering RDF in different parts of the page, do not keep history
	self.sparqlHTML = function(sparqlQuery, target)
	{
		queryNoHistory(encodeURIComponent(sparqlQuery),
			function(out) {transform.rdf2html(out, target);});
	};
	// Perform SPARQL query and show results as HTML in the target DOM element
	self.sparql = function(sparqlQuery)
	{
		self.showMessage("<p>Querying...</p>\n"+waitImage);
		query(encodeURIComponent(sparqlQuery),
			function(out) {self.showMessage("Showing...\n<img src='/html/images/black-loader.gif'/>"); transform.rdf2html(out, target);});
	};
	// SPARQL DESCRIBE query for the input URI
	self.describeResource = function(uri)
	{
		self.showMessage("<p>Describe "+uri+"</p>\n"+waitImage);
		query("DESCRIBE <"+escape(uri)+">",
			function(out) {self.showMessage("Showing...\n<img src='/html/images/black-loader.gif'/>"); transform.rdf2html(out, target);});
	};
	// SPARQL DESCRIBE query for all resources whose type is the input URI
	self.describeResourcesOfType = function(typeURI)
	{
		self.showMessage("<p>Describe resources of type</p><p>"+typeURI+"</p>\n"+waitImage);
		query("DESCRIBE ?r WHERE {?r a <"+escape(typeURI)+">}",
			function(out) {self.showMessage("Showing...\n<img src='/html/images/black-loader.gif'/>"); transform.rdf2html(out, target);});
	};
	// SPARQL DESCRIBE query for all resources connected to the input URI
	self.describeReferrers = function(uri)
	{
		self.showMessage("<p>Describe resources referring to<\p><p>"+uri+"</p>\n"+waitImage);
		query("DESCRIBE ?r WHERE {?r ?p <"+escape(uri)+">}",
			function(out) {self.showMessage("Showing...\n"); transform.rdf2html(out, target);});
	};
	// Edit the RDF description for the input URI
	self.editResourceDescription = function(uri)
	{
		queryNoHistory("DESCRIBE <"+escape(uri)+">",
			function(out) {transform.rdf2form(out, target);});
	};
	// New RDF description using that for the input URI as source
	self.newResourceDescription = function(uri)
	{
		queryNoHistory("DESCRIBE <"+escape(uri)+">",
			function(out) 
			{
				transform.rdf2form(out, target);
				document.editform.elements[0].value='Type Resource ID';
				document.editform.elements[0].focus();
				document.editform.elements[0].select();
			});
	};	
	// Put new data for the input URI in different formats (application/rdf+xml, application/n-triples or application/n3)
	self.putRDF = function(uri, metadata, format)
	{
		self.showMessage("<p>Sending...</p>\n"+waitImage);
		put(base, escape(uri), metadata, format,
			function(out) {window.location.reload();});
	};
	// Post new data in different formats (application/rdf+xml, application/n-triples or application/n3)
	self.postRDF = function(metadata, format)
	{
		self.showMessage("<p>Sending...</p>\n"+waitImage); 
		post(base, metadata, format,
			function(out) {self.showMessage("Showing...\n"); transform.rdf2html(out, target);});
	};
	// Delete the RDF description for the input URI
	self.deleteResourceDescription = function(uri)
	{
		del(base, escape(uri),
			function(out) {window.location.reload();});
	};
	// Show content in tab
	self.showTab = function(tabName, content)
	{
		var tabs = contentTabs.get('tabs'); // The rhizomik.contentTabs object is defined in WEB-INF/jsp/wikipage-view.jsp
		var tabPosition = tabs.length; //if new tab place last
		for(i=0; i<tabs.length; i++)
		{
			//Check if tab for service already exists and replace it
			if (tabs[i].get('label') == tabName)
			{
				tabPosition = i;
				contentTabs.removeTab(tabs[i]);
			}
		}
		var tab = new YAHOO.widget.Tab({label: tabName, content: content, active: true});
		contentTabs.addTab(tab, tabPosition);
	};
	// Show content in iframe in a tab 
	self.showIFrameTab = function(tabName, content)
	{ 
		var iframe = "<iframe name='"+service+"' height='400px' width='700px'></iframe>";
		iframe += "<script type='text/javascript'>";
		alert(out);
		iframe += "window.frames['"+service+"'].document.body.innerHTML =\'"+content.replace("\n", "", "g").replace("\r", "", "g")+"\';";
		iframe += "</script>";
		
		self.showTab(tabName, iframe); 
	};
	// Call service on resource description
	self.callServiceOnResource = function(service, endpoint, resourceURI)
	{
		queryNoHistory("DESCRIBE <"+escape(resourceURI)+">",
			function(description) 
			{
				post(
					//base+"/serviceproxy"+"?endpoint="+
					base+endpoint, description, 'application/rdf+xml', 
					function(out) { self.showTab(service, out); });
			});
	};
	
	return self;
};