/*
 * Rhizomer AJAX
 *
 * Author: http://rhizomik.net/~roberto
 * Author: Juanma Gimnez
 */

/****************************************************************************
 * Rhizomer SemanticForms Singleton
 ****************************************************************************/
rhizomik.SemanticForms = function()
{	/**
	 * Private Methods
	 */
    function isURI(uri)
	{
	    return (uri.indexOf("urn:")==0 || (uri.indexOf("://")>0 && uri.indexOf("\"")<0));
	};

	function isAnon(uri)
	{
		return (uri.indexOf("_:")==0);
	};

	function baseURL(url)
	{
	    return url.substring(0, url.lastIndexOf("/")+1);
	};

	function clearSelect(options)
	{
	    for(i=0; i<options.length; i++)
		options[i].selected = false;
	    options[0].selected = true;
	};
	
	function selectText(options, text)
	{
	    for(i=0; i<options.length; i++)
	    {
		if (options[i].text == text)
		    options[i].selected = true;
	    }
	};
	
	/**
	 * Public Methods
	 */
    return {
	    formToNTriples: function (form) {
			// If identifier not defined, use blank node
			var bNodeNum = 1;
			var baseID = '_:blank' + bNodeNum++;
			
		    var triples = '';
		    for (i=0; i<form.elements.length; i++)
		    {
				if (form.elements[i].name == 'http://www.w3.org/1999/02/22-rdf-syntax-ns#about' ||
						 form.elements[i].name == 'http://www.w3.org/1999/02/22-rdf-syntax-ns#ID')
				{
					if (form.elements[i].type=='text') 					// Get Base ID
						baseID = identifier = form.elements[i].value;
					else if (form.elements[i].value=='')				// Return to Base ID
						identifier = baseID;
					else
						identifier = form.elements[i].value;			// Use local ID, usually anonymous
					
					if (!isAnon(identifier)) 							// If not anonymous ID
						identifier = '<'+identifier+'>';
				}
				else if ((form.elements[i].type=='text' || form.elements[i].type=='hidden') && 
						 form.elements[i].value!='')
				{
					triples += identifier+' <'+form.elements[i].name+'> ';
					if (isURI(form.elements[i].value))
						triples += '<'+form.elements[i].value+'>';
					else if (isAnon(form.elements[i].value))
						triples += form.elements[i].value;
					else
					{
						var literal = form.elements[i].value.replace(/\"/g,"'");
						if (literal.indexOf("'") == 0 && literal.lastIndexOf("'") == literal.length-1)
							literal = literal.substring(1, literal.length-1);
						triples += '"'+literal+'"';
					}
// TODO: typed and language: "literal"@en "23"^^http://www.w3.org/2001/XMLSchema#int
					triples += ' .\n';
				}
				else if (form.elements[i].type=='select-one' && 
					 form.elements[i].options[form.elements[i].selectedIndex].value!="")
				{
					triples += identifier+' <'+form.elements[i].name+'> ';
					var selectedValue = form.elements[i].options[form.elements[i].selectedIndex].value;
					if (isURI(selectedValue))
						triples += '<'+selectedValue+'>';
					else if (isAnon(selectedValue))
						triples += selectedValue;
					else
						triples += '"'+selectedValue+'"';
					triples += ' .\n';
				}
		    }
		    return triples
		},
		
		//
		queryType: function (rhz,type)
		{
			var prefix = "\nPREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n PREFIX owl: <http://www.w3.org/2002/07/owl#>";
			var select = "\nSELECT ?p"; 
			var where1 = "\nWHERE {\n { ?p rdfs:domain ?d. \n  ?t rdfs:subClassOf ?d. \n FILTER (?t = <[types]> && ?d != rdfs:Resource) \n}\n UNION \n  {?r rdf:type owl:Restriction. \n ?r owl:onProperty ?p. \n ?t rdfs:subClassOf ?r. \n FILTER (?t = <[types]>)\n}}";
			x=where1.replace("[types]",type);
			where=x.replace("[types]",type);
			var query = prefix + select + where;
				
			rhz.describeResourcesOfType(type);
			rhz.sparqlRDF(query, function(out){ rhizomik.SemanticForms.processQueryType(out, rhz); });
		},

		//
		processQueryType: function (response, rhz)
		{
			var XML = new rhizomik.XMLFactory();
			var xmlResp = XML.createXMLDocFromText(response);
			var nodeArray = xmlResp.getElementsByTagName("value");
	 		if (nodeArray.length == 0)
		 		var nodeArray = xmlResp.getElementsByTagName("rs:value");

			var i = 0;
			var nameArray=[];
			var labelArray=[];
			var attributes;
			var resource;
					
			while(i<nodeArray.length)
			{
				attributes = nodeArray[i].attributes;
				resource = attributes.getNamedItem("rdf:resource");
				nameArray[i] = resource.nodeValue;
				labelArray[i] = nameArray[i].replace("#","/");	//CAMBIO PARA PODER ACCEDER TANTO A ETIQ. DE GENERICAS COMO ESPECIFICAS
				i++;
			}
	
			var x, y;
			var j=0;
			var label;
			var form = '<div> \n <form id="dynamic-form" name="dynamic-form">\n';
			var textInput = '<input type="text" name ="';
			var textInputs ='';
			var submitButton = '<input id="buttonS" type="button" name="buttonS" value="Submit" onclick="javascript:rhz.sparql(rhizomik.SemanticForms.formToSPARQL(getElementById(dynamic-form)))"/>\n';
	
			i=0;
			for (i=0; i<nameArray.length; i++)
			{
				label = "<p  class='Property'> ";
				x = labelArray[i].lastIndexOf('/');
				label += labelArray[i].slice(x+1);	
				textInputs += label + ':' + textInput + nameArray[i]+'"/></p>\n';
			}
			
			var ref ='<a href="#" id="add-property" style="text-decoration:none">+</a>';  
			form += textInputs + ref + "<br/>" + submitButton + '</form>\n' + '</div>';

			var prefix = "\nPREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n PREFIX owl: <http://www.w3.org/2002/07/owl#>";
			var select = "\nSELECT ?p";			
			var where = "\nWHERE \n{\n  ?p rdf:type ?t. \n FILTER (?t = rdf:Property || ?t = owl:DatatypeProperty || ?t=owl:ObjectProperty). \n";
			where += "OPTIONAL {?p rdfs:domain ?d}. \n FILTER (?d=rdfs:Resource || ! bound(?d)) \n }";
			var query = prefix + select + where;
			
			rhz.sparqlRDF(query, function(out){ rhizomik.SemanticForms.dynamicForm(out, rhz, form);});	
		},

		//
		dynamicForm: function (response, rhz, form)
		{
			var XML = new rhizomik.XMLFactory();
			var xmlResp = XML.createXMLDocFromText(response);
	 		var nodeArray = xmlResp.getElementsByTagName("value");
	 		if (nodeArray.length == 0)
		 		var nodeArray = xmlResp.getElementsByTagName("rs:value");
			
			var i = 0;
			var nameArray=[];
			var labelArray = [];
			var attributes;
			var resource;
			
			while(i<nodeArray.length)
			{
				attributes = nodeArray[i].attributes;
				resource = attributes.getNamedItem("rdf:resource");
				nameArray[i] = resource.nodeValue;
				labelArray[i] = nameArray[i].replace("#","/");	//CAMBIO PARA PODER ACCEDER TANTO A ETIQ. DE GENERICAS COMO ESPECIFICAS
				i++;
			}
			var x, y;
			var j=0;
			var label = [];
	
			i=0;
			for (i=0; i<nameArray.length; i++)
			{
				x = labelArray[i].lastIndexOf('/');
				label[i] = '"'+labelArray[i].slice(x+1)+'"';		
			}		
			
			i=0;
			var name = [];
			for (i=0; i<nameArray.length; i++)
			{
				name[i] = '"'+nameArray[i]+'"';		
			}
			
			var h1 = '';
			h1 += '<script type="text/javascript">\n';
			h1 += 'rhizomik.SemanticForms.newDialog();';
			h1 += '</script>\n';
			h1 += '<div id="panel-2">\n<div class="hd">Add a property</div>\n<div class="bd">\n';
			h1 += '<form name="add-newP" id="add-newP">\n <div id="myAutoComplete">\n<input id="myInput" type="text">\n<br><br>';
			h1 += '\n<div id="myContainer"></div>\n</div>\n';
			h1 += '<input id="myHidden" type="hidden"> \n </form>\n';
			h1 += '</div></div>\n';
			h1 += '<script type="text/javascript">\n';
			h1 += 'rhizomik.SemanticForms.autoComplete(['+name+'],['+label+']);';
			h1 += '</script>\n';
			form = form + h1;

			rhz.showTab("HTML", form);
		},

		//
		addInput: function (label, name) 
		{
			//aņadir un campo de texto con etiqueta: label i url: name en el formulario dinamico.

			
			/*	Poner una clase property a cada text input en el formulario.
			 Asi podemos guardar en un array todos los textinputs i cogemos el ultimo(con el 
			 getLastChild al final del formulario tendriamos el boton submit, una referencia, un salto de
			  paragrafo... )	tenemos que pasarle un objeto HTML con la informacion de la string
			  newInput a la funcion de insercion, a parte del nodo donde queremos colocarlo */

			
			var NI = document.createElement("p");
			NI.innerHTML = label + ':<input type="text" name="'+ name +'"/>';
			NI.className = "Property";			
					
			var inputArray = YAHOO.util.Dom.getElementsByClassName("Property", "p");
			if (inputArray.length > 0)
				YAHOO.util.Dom.insertAfter(NI, inputArray[inputArray.length-1]);
			else
			{
				YAHOO.util.Dom.insertBefore(NI, YAHOO.util.Dom.getFirstChild("dynamic-form"));
			}
		},

		//
		newDialog: function () 
		{
			
			var handleCancel = function() 
			{
				oPanel2.hide();
			}
			var handleSubmit = function() 
			{
				var lab1 = document.getElementById("myInput");
				var lab = lab1.value;
				
				var url1 = document.getElementById("myHidden");
				var url = url1.value;
				
				rhizomik.SemanticForms.addInput(lab, url);
				oPanel2.hide();
			}
	
			var oPanel2 = new YAHOO.widget.Dialog("panel-2", 
					{ width : "450px", fixedcenter : true, visible : false, 
					  constraintoviewport : true, modal: true, postmethod: "none",
					  buttons : [ { text:"Add", handler:handleSubmit, isDefault:true },
								  { text:"Cancel", handler:handleCancel } ]} );

			oPanel2.render();
			YAHOO.util.Event.addListener("add-property", "click", oPanel2.show, oPanel2, true);	

			var oTooltip2 = new YAHOO.widget.Tooltip("tooltip-2", 
				{ context:"add-property", 
				text:"Add a new property for the current resource",
				iframe: true, showDelay:500 });
		},

		//
		autoComplete: function (name, label) 
		{
			
			YAHOO.example.BasicLocal = function() 
			{
				var i = 0;
				var labelWithName = [];
				var labelWithNameJSON;
				
				while (i < name.length){
					
					labelWithNameJSON = '({label: "'+label[i]+'", url: "'+name[i]+'"})';
					labelWithName[i] = eval(labelWithNameJSON);
					i++;
				}
				
								
				
			    // Use a LocalDataSource
				var oDS = new YAHOO.util.LocalDataSource(labelWithName);
				// Optional to define fields for single-dimensional array
				oDS.responseSchema = {fields : ["label", "url"]};
				
				// Instantiate the AutoComplete
				var oAC = new YAHOO.widget.AutoComplete("myInput", "myContainer", oDS);
				oAC.prehighlightClassName = "yui-ac-prehighlight";
				oAC.useShadow = true;
				oAC.resultTypeList = false; 
				
				 var myHiddenField = YAHOO.util.Dom.get("myHidden"); 
				 	    var myHandler = function(sType, aArgs) { 
				 	        var myAC = aArgs[0];  
				 	        var elLI = aArgs[1];  
				 	        var oData = aArgs[2]; 
				 	         
				 	        // update hidden form field with the selected item's ID 
				 	        myHiddenField.value = oData.url; 
				 	        
				 	        
				 	    }; 
				 	    oAC.itemSelectEvent.subscribe(myHandler); 
				   
				return { oDS: oDS, oAC: oAC };
			}();    
		},

		//
		formToSPARQL: function (form)
		{
		    var wheres = "\nWHERE ";
		    var filters = "\nFILTER (";
		    var first = true;
		    for (i=0; i<form.elements.length; i++)
		    {
				if (form.elements[i].type=='text' && form.elements[i].value!="")
				{
				    if (first)
				    {
				    	wheres += '{\n';
				    	first=false;
				    }
				    else
				    { 
				    	wheres += '.\n '; 
				    	filters += '  &&  '; 
				    }
			
				    if (isURI(form.elements[i].value))
				    {
				        wheres += '?r   <'+form.elements[i].name+'>   ?x'+i;
				        filters += '?x'+i+' = <'+form.elements[i].value+'>';
				    }    
				    else
				    {
				    	if (form.elements[i].value.indexOf('*')>=0 || form.elements[i].value.indexOf('?')>=0)
				    	{
							x=form.elements[i].value.replace("*",".*");
							y=x.replace("?",".");
						    wheres += '?r   <'+form.elements[i].name+'>   ?x'+i;
						    filters += 'regex (?x'+i+', "'+y+'","i")';
						}
				    	else
				    	{
				    		wheres += '?r   <'+form.elements[i].name+'>   ?x'+i;
				    		//filters += '?x'+i+' = "'+form.elements[i].value+'"';
				    		filters += 'regex (?x'+i+', "'+form.elements[i].value+'","i")';
				    	}        
				    }
				}
				else if (form.elements[i].type=='select-one' && 
					 form.elements[i].options[form.elements[i].selectedIndex].value!="")
				{
				    if (first)
				    {
				     wheres += '{\n';
				     first=false;
				    }
				    else
				    { wheres += '.\n '; 
				      filters += '  &&  '; 
				    }		
				    
				    var selectedValue = form.elements[i].options[form.elements[i].selectedIndex].value;
				    if (isURI(selectedValue))
				    {	
				        wheres += '?r   <'+form.elements[i].name+'>   ?x'+i;
				        filters += '?x'+i+' = <'+selectedValue+'>';
				    }     
				    else
				    {
						 wheres += '?r   <'+form.elements[i].name+'>   ?x'+i;
				         filters += '?x'+i+' = "'+selectedValue+'"';
				    }
				}
		    }
		    //var query = "SELECT ?r "+wheres+'.'+filters+')\n}';
		    var query = "DESCRIBE ?r "+wheres+'.'+filters+')\n}';
		    return query;			
		}
    };
}();

/* DOCUMENTATION:

 * Get the properties defined as applying to any resource

   SELECT ?p
   WHERE 
   { 
      ?p rdf:type ?t. 
      FILTER (?t = rdf:Property || ?t = owl:DatatypeProperty || ?t=owl:ObjectProperty).
      OPTIONAL
      { ?p rdfs:domain ?d }.
      FILTER (?d=rdfs:Resource || ! bound(?d))
   }

 * Get the properties defined as applying to a specific kind of resources
 
   SELECT ?p
   WHERE 
   {
      {
         ?p rdfs:domain ?d.
         ?t rdfs:subClassOf ?d.
         FILTER (?t = swrc:Publication && ?d != rdfs:Resource) 
      }
      UNION 
      {
         ?r rdf:type owl:Restriction.
         ?r owl:onProperty ?p.
         ?t rdfs:subClassOf ?r.
         FILTER (?t = swrc:Publication)
      }
   } 
 */
