/**
 * Youfoot application wide Javascript namespace
 * 
 */
var YouFoot = {};

YouFoot.init = function (){
	for (var prop in this) {
		if (typeof this[prop].init == 'function') {
			if (this[prop].require != undefined) {
				var classes = this[prop].require.slice();
				classes.push(this[prop].init.bind(this[prop]));
				YouFoot.use.apply(window, classes);
			} else {
				this[prop].init();
			}
		}
	}
};

//
// Load any number of class objects from the classes dir 
// loads files asynchronously.
//
// Appends script tags to the document head.
//
// Example. YouFoot.use('MultiForm', 'Template', function () { .. });
// This will load MultiForm and Template classes and when they are done run the callback.
//
//
YouFoot.use = function () {
	function _appendScript(filename, callback) {
		var head = document.getElementsByTagName("head")[0];
		var script = document.createElement("script");
		script.src = filename;
		var done = false;
      
		script.onload = script.onreadystatechange = function () {
			if (!done && (!this.readyState || this.readyState == "loaded" || this.readyState == "complete") ) {
				done = true;
				callback();
			}
		}
		head.appendChild(script);
	}

	var compressorPath = window.basePath + 'asset_compress/js_files/join/';

	var classDir = window.basePath + 'js/classes/';
	var args = jQuery.makeArray(arguments);
	var readyCallback = Class.empty;

	if (typeof args[args.length -1] == 'function') {
		readyCallback = args.pop();
	}

	var filename = compressorPath + args.join('/');
	_appendScript(filename, readyCallback);
};


/**
 * i18n Object for JS translations
 *
 */
YouFoot.i18n = (function() {
	
	var _i18nDict = {};
	var i18n = {
	/**
	 * get a translated string from the translations dictionary
	 * @param [string] stringName name of string you want.
	 * @returns [string] Value of translated string
	 */
		get : function(stringName) {
			$.each(_i18nDict,function (i,val){
			//	alert(_i18nDict[i])
				//alert(i+ ',' +val + '  ');
				
			});
			  
			if (_i18nDict[stringName]) {
				return _i18nDict[stringName];
			}
			return stringName;
		},
	/**
	 * Set a value(s) to the dictionary.
	 * 
	 * @param [mixed] stringName either the stringname or a dictionary (object literal) to append
	 * @param [string] value Value of the stringname being added.
	 */
		set : function(stringName, value) {
			if (typeof(stringName) === 'string') {
				_i18nDict[stringName] = value;
			} else if (value === undefined) {
				for (var key in stringName) {
					_i18nDict[key] = stringName[key];
				} 
			}
		}
	}
	return i18n;
})();

var __ = YouFoot.i18n.get;

YouFoot.Templates = {};


/**
 * Create a basic prototypal inheritance Class.
 * 
 * Create new classes with Class.create({prototype object});
 * Extend a class with Class.extend({prototype object});
 * Tape on new methods to all existing instances with Class.implement({object});
 * 
 * Classes can have an init() function which acts as a constructor for the prototype
 */
function Class (features) {
	var klass = function (noStart) {
		if (typeof this.init == 'function' && noStart != 'noInit') {
			return this.init.apply(this, arguments);
		}
		return this;
	};
	for (var key in this) {
		klass[key] = this[key];
	}
	klass.prototype = features;
	return klass;
};

Class.prototype.extend = function (features) {
	var oldProto, oldFunc, newFunc, func;
	oldProto = new this('noInit');

	var makeParent = function(parent, current) {
		return function () {
			this.parent = parent;
			return current.apply(this, arguments);
		};
	};

	for (var key in features) {
		oldFunc = oldProto[key];
		newFunc = features[key];
		if (typeof oldFunc != 'function' || typeof newFunc != 'function') {
			func = newFunc;
		} else {
			func = makeParent(oldFunc, newFunc);
		}
		oldProto[key] = func;
	}
	return new Class(oldProto);
};

Class.prototype.implement = function (features) {
	for (var key in features) {
		this.prototype[key] = features[key];
	}
};

/**
 * Empty function good for comparing to empty functions
 */
Class.empty = function () { };



/**
 * Add bind function to all functions.
 *
 * lets change 'this' in any function.
 */
if (typeof Function.bind != 'function') {
	Function.prototype.bind = function (obj) {
		var method = this;
		return function() {
			return method.apply(obj, arguments);
		};
	}
}

// Convert CamelCase string to camel_case string.
if (typeof String.underscore != 'function') {
	String.prototype.underscore = function () {
		var underscored = this.replace(/([A-Z])/g, '_$1').toLowerCase();
		if (underscored.substr(0, 1) == '_') {
			return underscored.substring(1);
		}
		return underscored;
	}
}


YouFoot.alerts = {
	init : function() {
		if ($.fn.jqm == undefined) {
			return;
		}
		$('#alert').jqm({overlay: 40, modal : true, trigger : false});
		$('#confirm').jqm({overlay: 40, modal : true, trigger : false});
		$('.dialogClose').click(function(){
			$('#alert').jqmHide();
		});
	}
};

YouFoot.alert = function (msg, content) {
	$('#alert').jqmShow()
		.removeClass('error')
		.find('h2').html(msg)
		.end()
		.find('p').html(content);
};

YouFoot.error = function (msg, content) {
	$('#alert').jqmShow()
		.addClass('error')
		.find('h2').html('<span>' + msg + '</span>')
		.end()
		.find('p').html(content);
};

YouFoot.confirm = function (msg, callback, options) {
	if (options.yesValue) {
		$('#confirm .confirm-yes input').val(options.yesValue);
	}
	if (options.noValue) {
		$('#confirm .confirm-no input').val(options.noValue);
	}

	$('#confirm')
		.jqmShow()
		.find('p.message').html(msg)
		.end()
		.find(':submit:visible').unbind('click').bind('click', function (event) {
			if (this.value == $('#confirm .confirm-yes input').val()) {
				if (typeof callback == 'string') {
					window.location.href = callback;
				} else {
					callback();
				}
			}
			$('#confirm').jqmHide();
			return false;
		});
};


//
// Utility methods used in many places
//
var Utils = {
// Slide toggles an element, good for binding on click events
// ex. $(foo).bind('click', {text : 'one', textAlt : 'two', 'targetEl' : '#foo-bar'}, Util.toggleElement);
//
// @param string text Text state one
// @param string textAlt Text state two.
// @param string targetEl CSS selector for target to toggle.
//
	toggleElement : function(event) {
		var that = $(this);
		var selector = event.data.targetEl;
		var toggleText = function () {
			if (!event.data.text || !event.data.textAlt) {
				return;
			}
			if (that.text() == event.data.text) {
				that.text(event.data.textAlt);
			} else {
				that.text(event.data.text);
			}
		};
		$(selector).slideToggle('normal', toggleText);
		return false;
	}
};


var Validation = {
	notEmpty: function (value) {
		if (!value.length || value.length == 0) {
			return __('Must not be empty');
		}
		return true;
	},
	date: function (value) {
		if (!value.match(/(19|20)\d\d[- \/.](0[1-9]|1[012])[- \/.](0[1-9]|[12][0-9]|3[01])/)) {
			return __('Must be a valid date');
		}
		return true;
	},
	url: function (value) {
		//from CakePHP Validation::url()
		var pattern = /^(?:(?:https?|ftps?|file|news|gopher):\/\/)?(?:(?:(?:25[0-5]|2[0-4][0-9]|(?:(?:1[0-9])?|[1-9]?)[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|(?:(?:1[0-9])?|[1-9]?)[0-9])|(?:[a-z0-9][-a-z0-9]*\.)*(?:[a-z0-9][-a-z0-9]{0,62})\.(?:(?:[a-z]{2}\.)?[a-z]{2,4}|museum|travel))(?::[1-9][0-9]{0,3})?(?:\/?|\/([\!\"\$\&\\\'\(\)\*\+\,\-\.\@\_\:\;\=\/0-9a-z]|(%[0-9a-f]{2}))*)?(?:\?([\!\"\$\&\\\'\(\)\*\+\,\-\.\@\_\:\;\=\/0-9a-z]|(%[0-9a-f]{2}))*)?(?:#([\!\"\$\&\\\'\(\)\*\+\,\-\.\@\_\:\;\=\/0-9a-z]|(%[0-9a-f]{2}))*)?$/i;
		if (!value.match(pattern)) {
			return __('Must be a valid url');
		}
		return true;
	}
};


if (console === undefined) {
	var console = {
		log: function () {},
		error: function () {},
		trace: function () {}
	};
}


function findPos(obj) {
    var curleft = obj.offsetLeft || 0;
    var curtop = obj.offsetTop || 0;
    while (obj = obj.offsetParent) {
            curleft += obj.offsetLeft
            curtop += obj.offsetTop
    }
    return {x:curleft,y:curtop};
}

