
/** Shorthands **/
var Event = YAHOO.util.Event;
var Connect = YAHOO.util.Connect;
var $ = YAHOO.util.Dom.get;
var Dom = YAHOO.util.Dom;
var CustomEvent = YAHOO.util.CustomEvent;
var Selector = YAHOO.util.Selector;


var Orange = {};

Orange.addEvent = function(el, ev, call, args){
	args.push(el);
	Event.addListener(el, ev, call.createDelegate(this, args));
}

Orange.updateElement = function(url, target, options, source){
	new Orange.Updater(url, target, options, source);
}

Orange.Updater = function(url, target, options, source){
	
	this.url = url;
	this.target = target;
	
	if(options){
		if(options.callback)
			this.callback = eval(options.callback);
		if(options.scope)
			this.callbackScope = eval(options.scope);
		if(options.onclick)
			this.onclick = eval(options.onclick);
	}
	if(this.onclick){
		this.onclick(source);
	}
	this.request(options.post);
}

Orange.Updater.prototype = {
	request: function(postData){
		YAHOO.util.Connect.asyncRequest(
			'POST',  this.url, 
			{success: this.receive, 
			 failure: this.failure, 
			 scope: this},
			 postData? postData : ""
		);
	},
	
	receive: function(o){
		eval("var response = " + o.responseText);
		if(response && response.inner_html !== undefined){
			document.getElementById(this.target).innerHTML = response.inner_html;
		}
		if(this.callback){
			if(!this.callbackScope)
				this.callback(response);
			else
				this.callback.createDelegate(this.callbackScope, [response])();
		}
	}
}

Orange.Form = {

	submit: function(e, eargs, formId, url, target, loading, success){

		if(loading)
			loading();

		var args = YAHOO.util.Connect.setForm(formId);

		Connect.asyncRequest(
			'POST',  url,
			{success: Orange.Form.receive,
			 argument: [success, target]}, args
		);

		Event.preventDefault(e);
		
	},

	receive: function(o){

		eval("var response = " + o.responseText);

		if(response.inner_html !== undefined){
			document.getElementById(o.argument[1]).innerHTML = response.inner_html;
		}
		
		if(response.error !== undefined){
			
		}

		o.argument[0]();

	}

};

Orange.Util = {
	url: function(path){
		return Orange.baseUrl+path;
	},

	imgUrl: function(path){
		return Orange.baseImgUrl+path;
	},

	trim: function(str){
		return str.replace(/^\s+|\s+$/g, '') ;
	}
	
};

Orange.Array = {
	search: function(value, array){

		var index = -1;
		for(var i=0; i < array.length; i++){
			if(array[i]==value){
				index = i;
				break;
			}
		}
		return index;
		
	},

	is: function(array){
		return !!(array && array.constructor == Array);
	},

	flip: function(array){
		
		var flipped = {};
		for(var i=0; i < array.length; i++){
			flipped[array[i]] = i;
		}

		return flipped;
	}, 

	diffKey: function(a, b){
		var diff = {};
		for(var x in a){
			if(b[x]===undefined){
				diff[x] = a[x];
			}
		}
		return diff;
	},
	
	diff: function(a, b){
		var diff = {};
		for(var x in a){
			if(Orange.Array.search(x, b)==-1){
				diff[x] = a[x];
			}
		}
		return diff;
	}
}

Orange.Validator = {}

Orange.Validator.List = {};
Orange.Validator.Current = null;
Orange.Validator.DefaultErrorMessages = {};


Orange.Validator.Manager = function(id, error){
	this.init(id,error);
}

Orange.Validator.Manager.prototype = {
	validators: null,
	id: "",
	error: null,	

	init:function(id){
		this.id = id;
		this.validators = new Object();
		this.error = new Orange.Validator.Error();
	},

	attachToSubmit: function(){
		Event.addListener(this.id, 'submit', this.validate.createDelegate(this));
	},
	
	validate: function(e){
		
		var values = {};
		var uriString = Connect.setForm(this.id);
		var uriParts = uriString.split('&');
		
		for(var i=0; i < uriParts.length; i++){
			var pair = uriParts[i].split('=');
			var name = decodeURIComponent(pair[0]);
			
			var match = name.match(/(.+?)\[(.+?)\]$/);
			if(match){
				if(values[match[1]]===undefined)
					values[match[1]] = [];
				values[match[1]].push(match[2]);
			}
			else{
				values[name] = decodeURIComponent(pair[1]);
			}
			
		}
		
		var valid = true;
		for(var name in this.validators){
			
			var message  = this.validators[name].validate(values[name]);
			if(message != ""){
				this.error.show(name, message, this.id);
				valid = false;
			}
			else{
				this.error.hide(name, this.id);
			}
		}
		
		if(!valid){
			Event.preventDefault(e);
		}
		
		
	},

	addValidator: function(name, options, messages, config){
		this.validators[name] = new Orange.Validator.Instance(options, messages, config);
	}
}

Orange.Validator.Error = function(){}
Orange.Validator.Error.prototype =  {
	show: function(inputName, message){
		var element = document.getElementById("error_message_" + inputName);
		if(!element)return;
		element.innerHTML = message;
		element.style.display = "";
	},

	hide: function(inputName){
		var element = document.getElementById("error_message_" + inputName);
		if(!element)return;
		element.style.display = "none";
	}
}

Orange.Validator.Instance = function(options, messages, config){

	return {
		validate: function(value){

			if(config && config.array){
				if(value && !Orange.Array.is(value)){
					return "generic";
				}
				return this.validateArray(value);
			}

			if(config && config.file){
				return this.validateFile(value);
			}

			if(config && config.trim){
				value = Orange.Util.trim(value);
			}
			
			var isNull = Orange.Array.search(value, options['null_values']) != -1;
			
			if(options['required'] && isNull){
				return this.getErrorMessage('required');
			}

			if(isNull){
				return "";
			}

			if(options['expression'] && !value.match(new RegExp(options['expression']))){
				return this.getErrorMessage('expression');
			}

			if(options['in'] && Orange.Array.search(value, options['in'])==-1){
				return this.getErrorMessage('in');
			}

			if(options['max_length'] && value.length > options['max_length']){
				return this.getErrorMessage('max_length');
			}

			if(options['min_length'] && value.length < options['min_length']){
				return this.getErrorMessage('min_length');
			}

			var floatValue = parseFloat(value);
			
			if(options['max_value'] && floatValue > options['max_value']){
				return this.getErrorMessage('max_value');
			}

			if(options['min_value'] && floatValue < options['min_value']){
				return this.getErrorMessage('min_value');
			}

			return "";
		},

		validateArray: function(values){

			if(values===undefined) values = [];
			
			var nullCount = 0;
			
			for(var i=0; i < values.length; i++){
				if(Orange.Array.search(values[i], options['null_values']) != -1){
					nullCount++;
				}
			}

			if(options['required'] && (nullCount != 0 || values.length == 0)){
				return this.getErrorMessage('required');
			}

			if(options['array_max_required'] && (values.length - nullCount) > options['array_max_required']){
				return this.getErrorMessage('array_max_required');
			}

			if(options['array_min_required'] && (values.length - nullCount) < options['array_min_required']){
				return this.getErrorMessage('array_min_required');
			}
			
			if(options['array_required_keys']){
				for(var i=0; i < options['array_required_keys'].length; i++){
					if(values[options['array_required_keys'][i]] === undefined){
						return this.getErrorMessage('array_required_keys');
					}
				}
			}
			
			if(options['array_required_values']){
				for(var i=0; i < options['array_required_values'].length; i++){
					if(Orange.Array.search(options['array_required_values'][i], values)){
						return this.getErrorMessage('array_required_values');
					}
				}
			}
			
			if(options['array_count'] && values.length != options['array_count']){
				return this.getErrorMessage('array_count');
			}
			
			if(options['array_allow_duplicates']===false){
				var unique = array_unique(values);
				if(count(unique) != values.length){
					return this.getErrorMessage('array_allow_duplicates');
				}
			}

			if(values.length == nullCount){
				return true;
			}
			
			config.array = false;
			for(var i=0; i < values.length; i++){
				var message = this.validate(values[i]);
				if(message != ""){
					config.array = true;
					return message;
				}
			}

			config.array = true;
			return "";

		},

		validateFile: function(value){
			if(options['required'] && !value){
				return this.getErrorMessage('required');
			}
			
			if(options['extension'] && value){
				var extPattern = options['extension'].join('|');
				if(!value.match(new RegExp(".+\\."+extPattern+"$", "i"))){
					return this.getErrorMessage('extension');
				}
			}
			
			return "";
		},

		getErrorMessage: function(key){
			
			if(messages[key]){
				return messages[key];
			}
			if(Orange.Validator.DefaultErrorMessages[key]){
				
				return Orange.Validator.DefaultErrorMessages[key];
			}
			
			return Orange.Validator.DefaultErrorMessages['generic'];
		}
	}
}


//Thank to ExtJS for this
Function.prototype.createDelegate  = function(C,B,A){
	var D=this;
	return function(){
		var F=B||arguments;
		if(A===true){
			F=Array.prototype.slice.call(arguments,0);
			F=F.concat(B)
		}
		else{
			if(typeof A=="number"){
				F=Array.prototype.slice.call(arguments,0);
				var E=[A,0].concat(B);
				Array.prototype.splice.apply(F,E)
			}
		}
		return D.apply(C||window,F)
	}
}
