/**
 * FOX Cookies manager
 *
 * @package FOX
 * @subpackage JavaScript Library
 */

if (typeof Fox == 'undefined') {
	Fox = {};
}

Fox.Navigator = Class.create({
	
	initialize: function() {
		this.regex = /#(.*)$/i;
		this.location = '';
		this.handlers = [];
		this.queryParams = $H({});
		Event.observe(window, 'load', this.init.bind(this));
	},
	
	init: function() {
		this.pe = new PeriodicalExecuter(this.callback.bind(this), 0.1); // note: time passed in seconds
		//jQuery(window).bind('hashchange', this.callback.bind(this));
		
	},
	
	separator: '&',
	
	set: function(params) {
		var decode = params.decode;
		delete params.decode;
		
		console.log(params);
		
		if (typeof params == 'object') {
			params = Object.toQueryString(params, this.separator);
		}
		if (decode) {
			params = unescape(params);
		}
		
		var match = location.href.match(this.regex);
		if (match != null) {
			if (match[1].length) {
				location.href = location.href.replace(match[1], params);
			} else {
				location.href = location.href + params;
			}
		} else {
			location.href = location.href + '#' + params;
		}
	},

	unset: function(key) {
		if (this.queryParams.unset(key)) {
			this.set(this.queryParams);
		}
	},

	update: function(params) {
		if (typeof params != 'object') {
			return;
		}
		this.set(this.queryParams.merge(params));
	},
	
	get: function(key) {
		if (key) {
			return this.queryParams.get(key);
		}
		var match = location.href.match(this.regex);
		if (match != null) {
			return match[1];
		}
		return '';
	},
	
	getAll: function(prefix) {
		if (!prefix) {
			return this.queryParams;
		}
		var found = $H({});
		this.queryParams.each(function(value) {
			var pattern = new RegExp('^' + prefix + '_(.*)$');
			var matched = value[0].match(pattern);
			if (matched != null) {
				found.set(matched[1], value[1]);
			}
		}.bind(this));
		return found;
	},
	
	callback: function() {
		if (location.href != this.location) {
			var matchFrom = this.location.match(this.regex);
			this.location = location.href;
			var matchTo = location.href.match(this.regex);
			if (matchFrom != null) {
				var from = matchFrom[1];
				var changed = from.toQueryParams(this.separator);
			} else {
				var from = '';
				var changed = from.toQueryParams(this.separator);
			}
			if (matchTo != null) {
				var to = matchTo[1];
				var toParams = $H(to.toQueryParams(this.separator));
			} else {
				var to = '';
				var toParams = $H({});
			}
			//this.queryParams = this.queryParams.toObject();
			
			$H(changed).each(function(param){changed[param[0]] = false});
			toParams.each(function (param) {
				if (changed[param[0]] && changed[param[0]] == param[1]) {
					delete changed[param[0]];
				} else {
					changed[param[0]] = param[1];
				}
			}.bind(this));
			this.queryParams = toParams;
			this.relocate(from, to, changed);
		}
	},
	
	relocate: function(from, to, changed) {
		this.handlers.each(function(callback) {
			if (!callback[1]) {
				callback[0](from, to, changed);
			} else {
				var variables = callback[1], exists = false, found = {};
				var length = variables.length, i;
				for (i = 0; i < length; i++) {
					var pattern, matched, name;
					name = variables[i];
					if (typeof name == 'object') {
						pattern = name[1];
						name = name[0];
						if (typeof pattern != 'function') { //prefix mode
							pattern = new RegExp('^' + pattern + '_(.*)$');
						}
						for (prop in changed) {
							if (changed.hasOwnProperty(prop)) {
								matched = prop.match(pattern);
								if (matched != null) {
									if (!found[name]) {
										found[name] = {};
									}
									found[name][matched[1]] = changed[prop];
									exists = 1;
								}
							}
						}
					} else if (typeof changed[name] != 'undefined') {
						found[name] = changed[name];
						exists = 1;
					}
				}
				if (exists) {
					callback[0](from, to, found);
				}
			}
		});
	},
	
	handle: function(callback, variables) {
		this.handlers.push([callback, variables]);
	}
});
Fox.Navigator = new Fox.Navigator;

