/*
eRDF parser

author: Keith Alexander (http://semwebdev.keithalexander.co.uk/blog/)
license: GPL
usage:
	var parser = eRDF.parser(document);
	var triples = parser.get_triples();
	//smush
	parser.do_owlSameAs();
	var smushed_triples = parser.get_triples();
	//rdf/json
	var rdf_json = parser.get_JSON();
	// exhibit/json
	var exhibit_db = parser.get_ExhibitJSON();
*/
// setup the basic
if (typeof(eRDF) == 'undefined') {
    eRDF = new Object();
}

eRDF.reset = function() {
   // reset the triple container
   eRDF.triples = new Object();
   eRDF.bnode_counter = 0;
   eRDF.elements = new Object();
};

eRDF.reset();

//
// dummy callbacks in case they're not defined
//
if (!eRDF.CALLBACK_DONE_LOADING) eRDF.CALLBACK_DONE_LOADING = function() {};


eRDF.parser = function(document){	
	if(!document) document = window.document;
	
	this.get_base = function(){
		var bases= document.getElementsByTagName('base');
		if(bases.length){
			var base = bases[0].getAttribute('href');
		}else{ var base = location.href}
			
			return base+"#";
	};
	this._get_triples = function(el){
		var resource = this.get_base()+this._last_el_with_id(el);
		var pred_atts = ['class','rev','rel'];
		if (el.tagName.toLowerCase() == 'meta') pred_atts = ['name'];

		var pred_len = pred_atts.length;
		for (var i=0; i < pred_len; i++) {
			var att = pred_atts[i];
			this._get_triple(el, resource, att);
		};
		for (var i=0; i < el.childNodes.length; i++) 
		{
				if(el.childNodes[i].nodeType==1) this._get_triples(el.childNodes[i]);
		};
	};

	this._get_triple = function(el, resource, att){
	
	if(att=='class') var att_val =el.className;
	else var att_val = el.getAttribute(att);
		
			if (att_val && att_val.match('-'))
			{
				var att_names = att_val.split(' ');
				var att_len = att_names.length
				for (var i=0; i < att_len; i++)
				{
					var att_name = att_names[i];
					if(att_name.match('-'))
					{

						if(att=='class' && el.getAttribute('id'))
						{
							var rdftype = this.get_rdftype(att_name);	
							
							 if(rdftype)
							{
							 this.triples.push({"s":this.get_base()+el.getAttribute('id'),"p": this.rdf_type,"p_label":'rdf-type', "o": rdftype,"o_label":att_name });
							}
						}
						else if(this.get_predicate(att_name))
						{
							var o = this.get_object(el, att)	;
							var p = this.get_predicate(att_name) ;

							// rdfs:label images
							if(el.getAttribute('src') && el.getAttribute('title')) this.triples.push({"s":el.getAttribute('src'),"p": this.rdfs_label,"p_label":'rdfs-label', "o": el.getAttribute('title') });
							// rdfs:label anchors
							if(el.getAttribute('href') && (att=='rel'||att=='rev') && this.get_object(el, 'label') ) this.triples.push({"s":el.href,"p": this.rdfs_label,"p_label":'rdfs-label', "o": this.get_object(el, 'label') });
							//the triple, reversed for 'rev'
							if(att!='rev') this.triples.push({"s":resource,"p": p,"p_label":att_name, "o": o });
							else this.triples.push({"s":o,"p": p,"p_label":att_name, "o": resource });
						}
					}
				};
			}
	}
	

	this._last_el_with_id = function(el){

			if(el.getAttribute('id')) return el.id;
			else if(el.parentNode.nodeType==1) return this._last_el_with_id(el.parentNode);
			else return '';

	};


	this.get_object = function(el, att_type)
	{

		//welll, not always object, if @rev, s o will be reversed afterwards
		var el_title = el.getAttribute('title');
		var el_src = el.getAttribute('src');
		if(att_type=='class')
		{
			if (el_src) return el_src;
			else if(el_title) return el_title;
			else return (document.getElementsByTagName("body")[0].innerText != undefined)? el.innerText : el.textContent;
		}
		else if(att_type=='label')
		{
			if(el_title) return el_title;
			else return (document.getElementsByTagName("body")[0].innerText != undefined)? el.innerText : el.textContent;
		}
		else if(att_type=='rel' || att_type=='rev')
		{
			return el.href;
		}
		else if(att_type=='name')
		{
			return el.getAttribute('content');
		}
	}

	this.get_rdftype = function(class_att){ return this.check_type(class_att,  'rdftype'); }
	this.get_predicate = function(class_att){ return this.check_type(class_att,  "predicate"); }

	this.check_type = function(class_att, classType)
	{
		if(class_att.match('-'))
		{
			var found = false;
			for(prefix in this.schemas)
			{
				var regex = (classType=='rdftype')? '-'+prefix+'-' : prefix+'-';
				if(class_att.match(regex))
				{

					var regex_term = prefix+'-(.+)';
					
					found =  this.schemas[prefix]+class_att.match(regex_term)[1];
				}
			};
			return found;
		}
		else return false;
	}
	
	
	this.triples = [];
	this.schemas = {};
	this.rdf_type 	= 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type';
	this.rdfs_label = 'http://www.w3.org/2000/01/rdf-schema#label';
	this.links = document.getElementsByTagName('link');
	for (var i=0; i < this.links.length; i++) {
		if(this.links[i].rel.substring(0,7) == 'schema.')
		{
			var schema_name = this.links[i].rel.substring(7);
			this.schemas[schema_name] = this.links[i].href;
		}
	};

	//if(document.getElementsByTagName('head')[0].getAttribute('profile')=='http://purl.org/NET/erdf/profile') 
	this._get_triples(document.getElementsByTagName('html')[0]);
	this.get_triples = function(){ return this.triples;}
	this.get_JSON = function(){
	
	 var triples = this.do_owlSameAs();
		
		 this.json_objects = {};
			for (var i=0; i < triples.length; i++) {
				var triple = triples[i];
				if(!this.json_objects[triple.s]) this.json_objects[triple.s] = {};
				if(!this.json_objects[triple.s][triple.p_label]) this.json_objects[triple.s][triple.p_label] = [];
				if(triple.p_label=='rdf-type') this.json_objects[triple.s][triple.p_label].push(triple.o_label);
				else this.json_objects[triple.s][triple.p_label].push(triple.o);
			};

		return this.json_objects;
	};
	this.get_ExhibitJSON = function(){
		

						
			this.exhibit = {"properties":{}, "types":{},"items":[]};

			for (var i=0; i < this.triples.length; i++) 
			{
				var triple = this.triples[i];

				if (triple.p != this.rdf_type) 
				{
					if(triple.p != this.rdfs_label) this.exhibit.properties[triple.p_label] = {"uri":triple.p, "label": triple.p_label.split('-')[1]};
					else this.exhibit.properties[triple.p_label] = {"uri":triple.p, "label": triple.p_label};
					var label = triple.p_label;
					var item = { "id": triple.s };
					item[label] = triple.o;
					if(triple.p_label.match(/(name)|(title)|(label)/i)) item.label = triple.o;
					else item.label = triple.s; 
					//this.exhibit.items.push(item);
				}
				else
				{
					var label = triple.o_label.split('-')[2];
					this.exhibit.types[triple.o_label] = {"uri": triple.o, "label": label};
					var exhibit_label = this._get_label(triple.s);
					//this.exhibit.items.push({"id":triple.s, "type":triple.o_label,"label":exhibit_label});

				}
			};
			

			
			var obs = this.get_JSON();
			
			for (var k in obs)
			{

				var new_ob = {}; 
				var ob = obs[k];

				for(var p in ob)
				{
					new_ob[p]= ob[p]; 
				}

				
				new_ob.uri, new_ob.id = k;

				new_ob.label = this._get_label(k);

				new_ob.type = (new_ob['rdf-type'])? ob['rdf-type'][0].split('-')[2] : 'Item';
				this.exhibit.items.push(new_ob);

			}

		return this.exhibit;
	};

	this._get_label = function(subject){
		
		for (var i=0; i < this.triples.length; i++)
		{
			var triple = this.triples[i];
			if(triple.s == subject)
			{
				if(triple.p_label.match(/(name)|(title)|(label)/i)) return triple.o; 	
			}
		}
		return subject;
	};
	
	this.do_owlSameAs= function()
	{
		var same_ids = {};
		for (var i=0; i < this.triples.length; i++) 
		{
			var t = this.triples[i];
			if (t.p == 'http://www.w3.org/2002/07/owl#sameAs')
			{
				same_ids[t.s] = t.o;
				//remove owl-sameAs triple
				this.triples.splice(i,1);
			}
		};
		
			//change all matching triples
		for (var j=0; j < this.triples.length; j++) 
		{
			var t = this.triples[j];
			if (same_ids[t.s]) 
			{
				this.triples[j].s = same_ids[t.s];
			}
			else if (same_ids[t.o]) 
				 {
					this.triples[j].o = same_ids[t.o];
				 }
		}
		
		return this.triples;
	}
	
	return this;
};
		
eRDF.CALLBACK_DONE_LOADING();