
Orange.Module = {};

Orange.updateElement = function(e, e_args, url, target, params, source){
	var options = {post: Orange.Util.jsonToUrl(params)};
	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){
		Orange.Adapter.asyncRequest('POST', this.url, 
			{success: this.receive.createDelegate(this), failure: this.failure},
			postData? postData : "");
	},
	
	receive: function(o){

		var response = Orange.Adapter.parseJson(o);
		if(!response){return;}
		
		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])();
		}
	},

	failure: function(){
		
	}
};

Orange.Form = {

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

		if(loading)
			loading();

		var args = Orange.Adapter.getFormPost(formId);

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

		Orange.Adapter.Event.preventDefault(e);
		
	},

	receive: function(o){
		
		var response = Orange.Adapter.parseJson(o.responseText);
		if(!response) return;

		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){
		var parts = path.split('/');
		parts.splice(1, 0, 'images');
		path = parts.join('/');
		return Orange.publicUrl+path;
	},

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

	jsonToUrl: function(json){
		var result = [];
		for(var x in json){
			result[result.length] = x + "=" + json[x];
		}
		return result.join("&");
	}
	
};

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;
	},
	clean: function(actual, deleteValue){
	  var newArray = new Array();
	  for(var i = 0; i< actual.length; i++){
		  if (actual[i] != deleteValue){
			newArray.push(actual[i]);
		}
	  }
	  return newArray;
	},
	unique: function(inputArr){
		//From phpjs.org

		var key = '',
			tmp_arr2 = [],
			val = '';

		var __array_search = function (needle, haystack) {
			var fkey = '';
			for (fkey in haystack) {
				if (haystack.hasOwnProperty(fkey)) {
					if ((haystack[fkey] + '') === (needle + '')) {
						return fkey;
					}
				}
			}
			return false;
		};

		for (key in inputArr) {
			if (inputArr.hasOwnProperty(key)) {
				val = inputArr[key];
				if (false === __array_search(val, tmp_arr2)) {
					tmp_arr2[key] = val;
				}
			}
		}

		return tmp_arr2;

	}
}

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: "",

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

	attachToSubmit: function(){
		Orange.Adapter.Event.addListener(this.id, 'submit', this.validate.createDelegate(this));
	},
	
	validate: function(e){
		
		var values = [];
		var uriString = Orange.Adapter.getFormPost(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]][match[2]] = decodeURIComponent(pair[1]);
			}
			else{
				values[name] = decodeURIComponent(pair[1]);
			}
		}

		var error = new Orange.Validator.Error();
		
		var valid = true;
		for(var name in this.validators){
			var message  = this.validators[name].validate(values[name]);
			if(message != ""){
				error.show(name, message, this.id);
				valid = false;
			}
			else{
				error.hide(name, this.id);
			}
		}
		
		if(!valid){
			Orange.Adapter.Event.preventDefault(e);
		}
		
		
	},

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

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

		hide: function(inputName, formId){
			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);
			}

			if(config.callback){
				var func = eval(config.callback);
				if(func(value) == false){
					return this.getErrorMessage('callback');
				}
			}

			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 cleaned = Orange.Array.clean(values, "");
				var unique = Orange.Array.unique(cleaned);
				if(unique.length != cleaned.length){
					return this.getErrorMessage('array_allow_duplicates');
				}
			}

			if(values.length == nullCount){
				return "";
			}
			
			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);
	}
}

