/*
jQuery Compare - 01/06/10
VERSION 0.7a
by Craig Eve <evelution.net>

jQuery Compare is distributed under the MIT License
Read more about the MIT License --> http://www.opensource.org/licenses/mit-license.php

This script is currently a beta test version, download and use it at your own risk.
The jQuery Compare developer shall have no responsibility for data loss or damage of any kind by using this script.

Proposed future development:
0.9a:	- new function for testing only existence of URI components/query string variables, regardless of value
		- add support for anchored links that don't cause refreshes
			- possibly include simplified history plugin here.
			- see if possible to include anchor state reloading and auto-ajax replacement
		

This plugin makes use of parseUri
// parseUri 1.2.2
// (c) Steven Levithan <stevenlevithan.com>
// MIT License

*/

(function($) {
	$.fn.compare = function(options) {
		var options = $.extend({}, $.fn.compare.defaults, options);
		var newCollection = testCollection = $([]);
		this.each(function() {
			$this = $(this);
			testCollection = testCollection.add($this.is('a') ? $this : $this.find('a')); // Check if current object is anchor, else find descendent anchors
		});
		testCollection.each(function(i){
			$this = $(this);
			var opts = options;//$.meta ? $.extend({}, options, $this.data()) : options;
			//if ($.meta) { opts.query = $.extend({}, options.query, opts.query); }
			var url = parseUri(opts.url);
			var this_url = parseUri($this.attr('href')); // Parse this link
			error = false; // Reset error status
			$.each(opts.query, function(k,v) { // Run query string comparison here
				error = error || ((typeof this_url.get[k] != 'string' && v) || (typeof this_url.get[k] == 'string' && url.get[k] != this_url.get[k])); // error if (already found an error) or (not_set & required) or (set & doesn't match)
			});
			$.each(opts.compare, function(k,v) { // Run standard component comparison here
				//console.log(typeof this_url[k] + ' - this_k:' + this_url[k] + ' - url_k:' + url[k] + ' - v:' + v);
				error = error || (
						(this_url[k] == '' && v) || 
						(this_url[k] != '' && url[k] != this_url[k])
						); // error if (already found an error) or (not_set & required) or (set & doesn't match)
			});
			if (!error) {
				newCollection = newCollection.add(this); // Add matches to result jquery object
			}
		});
		return(this.pushStack(newCollection, 'compare', ''));
	}
	$.fn.query = function(options) { // Direct query string comparison - alias of compare({'query':{}})
		return this.compare({'query':options}); // Convert to query string shortcut
	}
	$.getUri = function(str) {
		var options = $.extend({}, $.fn.compare.defaults);
		if (typeof str == 'string') options.url = str;
		return parseUri(options.url)
	}
	log = typeof console == "object" ? console.log:function(){}; // console.log alias
	function parseUri(str) {
		var	o	= $.fn.compare.defaults.parseUri,
			m	= o.p[o.s ? "s" : "l"].exec(str),
			u	= {},
			i	= 14;
		while (i--) u[o.k[i]] = m[i] || "";
		u[o.k[11]] = (u[o.k[2]] == u[o.k[6]] && u[o.k[11]] == '') ? u[o.k[2]] : u[o.k[11]]; // find missing file in short url
		u[o.q.n] = {};
		u[o.k[12]].replace(o.q.p, function ($0, $1, $2) {
			if ($1) u[o.q.n][$1] = $2;
		});
		return u;
	}
	$.fn.compare.defaults = {
		url		: window.location,			// Default to current page
		compare	: {},						// For comparing normal URI elements
		query	: {},						// For comparing individual query string elements
		parseUri: {
			s: false,						// strict: Allow a broader URI format
			k: [							// key: Name of each URI component
				"source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"
			],
			q:   {							// q: query string variables
				n:   'get',					// name: Name of query string object
				p: /(?:^|&)([^&=]*)=?([^&]*)/g // parser: Regex for parsing query string
			},
			p: {						// parser: Regex for parsing the supplied URI
				s: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, // strict
				l: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ //loose
			}
		}
	};
})(jQuery);
