var COP = {

	BASKET:{}, 	//basket data
	UI:{},		//UI
	CONF:{},	//config
	API:{},		//API
	DATA:{},	//data (products and prices)
	UTILS:{},	//common functions
	OBJECTS:{},	//Object prototypes
	PROMOS:{},	//promos
	AB:{}		//AB testing
	
}

//shortcuts
var D, C, B, F, UI, API, OO, P, AB;

D=COP.DATA;
C=COP.CONF;
B=COP.BASKET;
F=COP.UTILS;
UI=COP.UI;
API=COP.API;
OO=COP.OBJECTS;
P=COP.PROMOS;
AB=COP.AB;

OO.products = {};

//############# OO ###################
OO.Domain_search = function(API, UI, CONF) {
	
	var self = this;
	this.CONF = new CONF(self);
	this.API = new API(self);
	this.UI = new UI(self);
	
	$(self).bind('domain_results_ready', function(e,data_obj) {
		//console.log('domain_results_ready callback');
		self.present_results(data_obj);
	});
	
	$(self).bind('domain_call_unsuccessful', function(e,data_obj) {
		var r = new OO.Request('/order/domain-search', 'get',	[
															{
																name:'domain',
																value:data_obj.host_ext.hostname+data_obj.host_ext.extension
															}
																]);
		r.send();
	});
	
	$(self).bind('domain_chosen', function(e,input) {
		if (observing.length) {
			$(observing).each(function(i,val) {
				$(val).trigger('domain_chosen', [input])
			});
		}
	});
	
	$(self).bind('item_in_basket_OK', function(e,data) {
		$(this.UI).trigger('item_in_basket_OK',[data])
	});
	
	$(self).bind('domain_search_initiated', function(e,data_obj) {
		$(this.UI, this.API).trigger('domain_search_in_progress');
		self.get_results(data_obj);
	});
	
	$(self).bind('last_domain_deleted', function(e) {
		$(this.UI).trigger('show_domain_search_input');
	});
	
	$(self).bind('too_little_input', function(e) {
		$(this.UI).trigger('show_more_input_prompt');
	});
	
	var observing = [];
	
	this.subscribe = function(obj) {
		observing.push(obj);
	}
	
	this.get_results = function(data_obj) {
		
		self.get_more_results(data_obj);
		
	}
	
	this.get_more_results = function(data_obj) {
		
		if (this.CACHE.extensions_index && this.CACHE.extensions_index < this.CONF.api.extensions.length) {
			this.CACHE.extensions_index++;
		}
		
		if (this.CONF.api.extensions.length) {
			this.CACHE.current_extensions = this.CONF.api.extensions[this.CACHE.extensions_index];
		}

		this.API.check_domain_availability(data_obj);
			
	};
	
	this.present_results = function(data_obj) {
		$(this.UI).trigger('present_domain_results', [data_obj]);
	};
		
	this.init = function() {
		$(this.UI).trigger('domain_search_object_ready');
	};
	
	//all should be static
	this.CACHE = {
		extensions_index:0,
		current_extensions:[]
	};

};

OO.Request = function(action, method, fields) {
	
	var form_html = ['<form action="'+(action||'')+'" method="'+(method||'post')+'">'];
	
	for (var i=0; i<fields.length; i++) {
		
		form_html.push('<input type="'+(fields[i].type||'hidden')+'" name="'+fields[i].name+'" value=\'',
						fields[i].value,
						'\' />');
			
	}
	
	form_html.push('</form>');
	
	//console.log(form_html.join(''));
	
	var $form = $(form_html.join(''));
	
	//console.log($form.html())
	
	this.send = function() {
		$('body').append($form);
		//console.log($form.serialize())
		$form.submit();
	}
	
	var destroy = function() {
		$form.remove();
	}
};

OO.Daemon = function(interval) {

	var handle = setInterval(function() {
		
		var i = 0;
		
		while(functions[i]) {
			var fn = functions[i];
			var scope = fn.scope || null;
			var args = fn.args || [];
			fn.apply(scope, args);
			i++;
		}
	
	},interval||250);
	
	var functions = [];
	
	this.kill = function() {
		clearInterval(handle);
	}
	
	this.add_process = function(fn) {
		return functions.push(fn) - 1;
	}
	
	this.remove_process = function(index) {
		functions.splice(index,1);
	}
	
};

OO.extend = function(target, source) {
	for (var o in source) {
		target[o] = source[o];
	}
	return target;
}

//############# F ###################

F.create_cookie =		function(name,value,days) {
									if (days) {
										var date = new Date();
										date.setTime(date.getTime()+(days*24*60*60*1000));
										var expires = "; expires="+date.toGMTString();
									}
									else {
										var expires = "";
									}
									document.cookie = name+"="+value+expires+"; path=/";
						};

F.read_cookie = 		function (name) {
									var nameEQ = name + "=";
									var ca = document.cookie.split(';');
									for (var i=0; i < ca.length; i++) {
										var c = ca[i];
										while (c.charAt(0)==' ') {
											c = c.substring(1,c.length);
										}
										if (c.indexOf(nameEQ) == 0) {
											return c.substring(nameEQ.length,c.length);
										}
									}
									return null;
						};

F.erase_cookie =		function(name) {
									DAC.utils.createCookie(name,"",-1);
						};
								
F.get_hostname_extension = function(domain_input, extensions) {
	
	var hostname =	domain_input.toLowerCase(),
		extension =	'';
	
	if(domain_input.indexOf('www')===0){
		//get rid of www and assign new value to var
		hostname = domain_input.replace('www.', '');		
	};

	//roughly sanitize
	hostname = hostname.replace(/[^\w-.]/g,'');
	
	//correct order of validating domain
	//1. sanitize roughly
	//this will make sure that space or weird characters in final position
	//don't interfere with extension recognision
	//like www.-sdas-12()&.com%
	//2. identify and chop off extension
	//3. sanitize thoroughly the remaining hostname
	
		for (var i=0;i<extensions.length;i++) {
			
			var ext = extensions[i];
			//if extension can be found in domain input
			//and found extension is in the last position
			//and found extension is the longest found extension
			if (hostname.lastIndexOf(ext) > 0 && hostname.lastIndexOf(ext) + ext.length === hostname.length && ext.length>extension.length) {
					extension = ext;
					var ext_index = hostname.lastIndexOf(ext);
			}
		}
	
	
	
	if (extension) {
		hostname = hostname.substring(0,ext_index);
	}
	
	return {
				hostname:hostname
				,
				extension:extension
		
			};
			
};

F.cleanup_hostname = function(hostname, extension) {
	
	//3-63 characters, alphanumeric+'-'
	var re=/[^\w-]/g;

	//add dot for name
	if (extension==='.name') {var re=/[^\w\.{1}-]/g}

	var re2=/(^-)-*/;
	var re3=/-*(-$)/;
	var re4=/_/g;


	hostname=hostname.replace(re,'').replace(re2,'').replace(re3,'').replace(re4, '').toLowerCase();

	hostname=hostname.substr(0,63);

	//change it to an empty string if it's undefined
	hostname=hostname||'';

	return hostname;

};

F.cleanup_username = function(username) {
	
	username = username.toLowerCase();
	
	//2-16 characters, [az]
	var re=/[^a-z]/g;
	var re1=/_/g;

	username=username.replace(re,'').replace(re1,'');
	
	username=username.substr(0,16);
	
	//change it to an empty string if it's undefined
	username=username||'';

	return username;

};

F.to_price =						function format_price(num_amount, str_currency) {
										
										//returns nicely formatted price
										//with 2 decimal places
										
										var price, symbol;
										
										if (typeof num_amount === 'number') {
											
											switch (str_currency) {
											
													case 'GBP':
													symbol='&pound;';
													break;
													
													case 'USD':
													symbol='&#36;';
													break;
													
													default:
													symbol='&pound;';
													break;
											
											}
											
											return symbol+num_amount.toFixed(2);
										
										}
										
										else {
											
											if (typeof num_amount === 'string') {
												
												var converted = +num_amount;
												
												if (!isNaN(converted)) {
												
													return format_price(converted, str_currency);
												
												}
												
											}
											
										}
										
										return '';
										
									
									};
									
F.format_price = F.to_price;

F.get_scroll =						function() {
	
										var scrOfX = 0, scrOfY = 0;
	
										if( typeof( window.pageYOffset ) == 'number' ) {
										//Mozilla compliant
											scrOfY = window.pageYOffset;
											scrOfX = window.pageXOffset;
										}
										
										else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
											//DOM compliant
											scrOfY = document.body.scrollTop;
											scrOfX = document.body.scrollLeft;
										}
										
										else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
											//IE6 standards compliant mode
											scrOfY = document.documentElement.scrollTop;
											scrOfX = document.documentElement.scrollLeft;
										}
										
										return [ scrOfX, scrOfY ];
			
									};

F.to_JSON_string = 			function(obj) {
			
									var isArray=function(_obj) {
									return _obj instanceof Array;
									};
									
									var isObject=function(_obj) {
									return (_obj instanceof Object) && !(_obj instanceof Array);
									};
									
									var isString=function(_obj) {
									return !!(typeof _obj =='string');
									};
									
									var isNumber=function(_obj) {
									return !!(typeof _obj =='number');
									};
									
									var qt = function(str) {
									return "\""+str+"\"";
									};
											if (isArray(obj)) {
													var output=[];
													for (var i=0,l=obj.length;i<l;i++) {
													output.push(arguments.callee(obj[i]));
													}
													return '['+output.join(', ')+']';
											}
									
											if (isObject(obj)) {
													var output=[];
													for (var i in obj) {
													output.push(qt(i)+":"+arguments.callee(obj[i]));
													}
													return '{'+output.join(', ')+'}';
											}
									
											if (isString(obj)) {
													return qt(obj);
											}
									
											if (isNumber(obj)) {
													return obj;
											}
									
								};

F.get_location_object = 		function() {

									var query_string, params_arr, params = {};

									try {
										query_string=decodeURIComponent(location.search.substr(1));
									}
									catch (e) {
										query_string = '';
									}
									
									function split_and_push(str) {
										
										var pair = str.split('=');
										params[pair[0]] = pair[1];
										
									};
									
									if (query_string) {
										
										if (query_string.indexOf('&')>=0) {
											
											//console.log(query_string);
											
											params_arr = query_string.split('&');
											
											var i = 0;
											while(params_arr[i]) {
												split_and_push(params_arr[i]);
												i++;
											}
											
										}
										
										else {
											split_and_push(query_string);
										}
									}
									
									return params;

								};

F.to_object = 					function(str_JSON) {
									if (str_JSON.indexOf('{')==0 && str_JSON.lastIndexOf('}')==str_JSON.length-1) {
										return eval('(' + str_JSON + ')');
									}
									else {
										return null;
									}
								};


//UI
UI.populate_select =       		function(source,value,label,preselected) {

									//value and label are in relation to source

									var r = [];

									for (var o=0;o<source.length;o++) {

											r.push('<option '+
															(preselected === o ? 'selected="selected "':'')+
															(value?'value="'+source[o][value]:'')+'"'+
															'>'+
															label.call(source[o])+
															'</option>');
									};

									return r.join("\n");

								};
								
UI.populate_select2 = 			function(options, preselected) {
									
									//console.log(arguments);
									
									function value(obj, data_row) {
										if (obj.call) {
											return obj.call(data_row);
										}
										else {
											return obj;
										}
									}
								
									var ret = [];
									
									for (var o=0;o<options.length;o++) {
												
												//console.log(value(preselected, options[o]), value(options[o].value,options[o]), 'value')
												
												var selected = preselected ? (value(preselected, options[o]) === value(options[o].value,options[o]) ? 'selected="selected "':'') : '';
												
												ret.push('<option '+selected 
																+
																(value(options[o].value,options[o])?'value="'+value(options[o].value,options[o]):'')+
																'">'+
																value(options[o].label,options[o])+
																'</option>');
									
									};
									
									return ret.join("\n");
									
								
								};
								
UI.prepare_choice = function(options,preselected,single_fn) 	{
								
								var ret;
								
								if (options.length>0) {
								
									if (options.length>1) {
										
										ret = '<select>'+UI.populate_select2(options, preselected)+'</select>';
										
									}
									
									else {
										
										if (!single_fn && typeof options[0].label==='function') {
											
											single_fn = function () {return '<span>'+this.label()+'</span>'};
										
										}
										
										ret = single_fn.call(options[0]);
										
									}
								
								}
								
								else {
									
									ret = '';
								
								}
								
								return ret;
						
							}
							