/**
 * Implements Turtle Styles
 *
 * @author Toby Inkster
 * @license http://www.gnu.org/licenses/agpl-3.0.html
 * @seealso http://buzzword.org.uk/2009/turtle-style/
 */ 

var PREFIX_STYLE = "http://ontologi.es/turtle-style#";
var PREFIX_RDF   = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";

$(document).ready(function ()
{
	var $turtleStyles = $('style[type="text/turtle"]');
	var $parser       = new ParseTurtle;
	$turtleStyles.each(function()
	{
		try
		{
			var $triples = $parser.parse($(this).text());
			var $rdfjson = triples_to_rdfjson($triples);
			
			if (typeof $rdfjson[""][PREFIX_STYLE + "sequence"] != 'undefined')
			{
				for (var $i in $rdfjson[""][PREFIX_STYLE + "sequence"])
				{
					rdf_style($rdfjson[""][PREFIX_STYLE + "sequence"][$i]["value"], $rdfjson);
				}
			}
		}
		catch ($err)
		{
			if (typeof console != 'undefined'
			&&  typeof console.log != 'undefined')
				console.log("Syntax error found in Turtle.");
		}
	});
});

/**
 * Converts ParseTurtle's triple-based output format to Talis' RDF/JSON structure.
 */
function triples_to_rdfjson ($T)
{
	var $rv = {};
	
	for (var $i in $T)
	{
		var $t = $T[$i];
		
		var $subj  = $t.subject.replace(/^genid:/, '_:genid');
		var $pred  = $t.predicate;
		var $obj   = $t.object.replace(/^genid:/, '_:genid');
		var $otype = $t.type;
		
		if ($otype == 'resource')
		{
			if ($obj.match(/^_:/))
				$otype = 'bnode';
			else
				$otype = 'uri';
		}
		
		if (typeof $rv[$subj] == 'undefined')
			$rv[$subj] = {};
		
		if (typeof $rv[$subj][$pred] == 'undefined')
			$rv[$subj][$pred] = new Array();
		
		$rv[$subj][$pred].push({
			'value'    : $obj ,
			'datatype' : $t.datatype , 
			'lang'     : $t.lang , 
			'type'     : $otype
			});
	}
	
	return $rv;
}

/**
 * Implements a given Style RuleSet.
 */
function rdf_style ($rule_id, $rdfjson)
{
	var $first = $rdfjson[$rule_id][PREFIX_RDF + "first"][0]["value"];
	
	if (typeof $rdfjson[$first] != 'undefined'
	&&  typeof $rdfjson[$first][PREFIX_STYLE + "selector"] != 'undefined')
	{
		var $nsResolver = document.createNSResolver( document.documentElement );
		
		for (var $s in $rdfjson[$first][PREFIX_STYLE + "selector"])
		{
			var $selector    = rdf_style_value($rdfjson[$first][PREFIX_STYLE + "selector"][$s], $rdfjson);
			var $xpathResult = document.evaluate($selector, document, $nsResolver, XPathResult.ANY_TYPE, null);
			
			var $elements = new Array();
			var $element  = $xpathResult.iterateNext();
			while ($element)
			{
				$elements.push($element);
				$element = $xpathResult.iterateNext();
			}
			
			for (var $e in $elements)
			{
				$element = $elements[$e];
			
				for (var $p in $rdfjson[$first])
				{
					if ($p.substr(0, PREFIX_STYLE.length) == PREFIX_STYLE)
					{
						var $style_prop  = $p.substr(PREFIX_STYLE.length);
						var $style_value = rdf_style_value($rdfjson[$first][$p][0], $rdfjson);
						
						if ($style_prop != 'selector' && $style_value != null)
							$element.style[$style_prop] = $style_value;
					}
				}
			}
		}
	}
	
	if (typeof $rdfjson[$rule_id][PREFIX_RDF + "rest"] != 'undefined')
	{
		var $rest = $rdfjson[$rule_id][PREFIX_RDF + "rest"][0]["value"];
		if ($rest == PREFIX_RDF + "nil")
		{
			return true;
		}
		else
		{
			return rdf_style($rest, $rdfjson);
		}
	}
}

/**
 * Returns the literal value of a resource using rdf:value.
 */
function rdf_style_value ($object, $rdfjson)
{
	if ($object.type == 'literal')
		return $object.value;
	
	if ($rdfjson[ $object.value ] == 'undefined')
		return null;

	if ($rdfjson[ $object.value ][ PREFIX_RDF + "value" ] == 'undefined')
		return null;
	
	return rdf_style_value($rdfjson[ $object.value ][ PREFIX_RDF + "value" ][0], $rdfjson);
}

