/**
 * @author roger
 */
var tb = {};

tb.toJSON = function(data){ eval("var a = " + data); return a; }

tb.popup = function(html){
	var visible = true;
	if (jQ('#admin_popup').length == 0) {
		visible = false;
		jQ('body').append('<div id="admin_popup"><a id="close_admin_popup" href="#" onclick="jQ(\'#admin_popup\').remove();return false;">close</a><div id="admin_popup_content"></div></div>');
	}
	if (html == 'loading') {
		jQ('#admin_popup_content').html('<div id="admin_popup_loading"></div>');
		tb.center('#admin_popup');
		jQ('#admin_popup').fadeIn(200);
	} else {
		jQ('#admin_popup').hide();
		jQ('#admin_popup').show();
		jQ('#admin_popup_content').html(html);
		tb.center('#admin_popup');
	}
}

tb.progressbar = function(options) {
	if (!options) {
		jQ('#admin_popup').remove();
		return;	
	}
	var title = options.title;
	var progress = options.progress;
	var total = options.total;
	var w = Math.floor((progress/total)*100);
	cb.console('progress bar width: '+w+'%');
	var html = '<h3 id="tb_progress_title">'+title+'</h3><div id="tb_progress"><div id="tb_progress_bar" style="width:'+w+'%;"></div></div>';
	tb.popup(html);
}

tb.loading_indicator = function(enable) {
	if (enable) {
		jQ('#admin_content').append('<div id="cms_loading"></div>');
	} else {
		jQ('#cms_loading').fadeOut(200);
	}
}

tb.center = function(object) {
	var width = jQ(object).width();
	var height = jQ(object).height();	
	var containerWidth = jQ(window).width();
	var containerHeight = jQ(window).height();
	
	width = width/2;
	height = height/2;
	containerWidth = containerWidth/2;
	containerHeight = (containerHeight/2);
	
	var leftOffset = containerWidth - width;
	var topOffset = containerHeight - height + +jQ(window).scrollTop();
	if (topOffset < 20) {
		topOffset = 20;
	}
	
	jQ(object).css('left', leftOffset+'px').css('top', topOffset+'px');
}

tb.purr = function(data, options) {
	var purr = cms.get_tpl(tb.purr.tpl, data);
	var defaults = { fadeInSpeed: 100, fadeOutSpeed: 200, removeTimer: 4000, isSticky: false, usingTransparentPNG: false };
	options = (options) ? jQ.extend(defaults, options) : defaults;
	jQ(purr).purr(options);
}

//arg is an array of the nested json data. Checks if each level exists without generating errors. ex: [weToolTipData, 'cssref', 'top'] would check for weToolTipData.cssref.top 
//The first index in the array must be the entire json data, the rest are strings of the keys we are diving through to check for
tb.jsonExists = function(arr) {
	var checked = arr[0];
	if (checked) {
		for (i = 1; i < arr.length; i++) {
			if (checked[arr[i]]) {
				//cb.console('jsonExists: found '+arr[i]);
				checked = checked[arr[i]];
			} else {
				cb.console('jsonExists: could not find '+arr[i]);
				return false;
			}
		}
	}
	return checked;
}

tb.photoselect = function(options) {
	this.container = jQ(options.container);
	this.cat_select = jQ(options.cat_select);
	this.photo_holder = jQ(options.photo_holder);
	this.input = jQ(options.photo_id_input);
	this.finder = jQ(options.search_input);
	this.original_photo = jQ(options.original_photo);
	this.image_size = options.image_size;
	this.image_bg = options.image_bg;

	this.original_photo_id = this.input.attr('value'); 
	
	this.input.after('<input type="hidden" id="cdn_thumb_url" name="cdn_thumb_url" value="'+this.original_photo.attr('class').split('?')[0].replace(CDN_BASE, '')+'"/>');
	this.hidden_thumb_input = jQ('#cdn_thumb_url');
	
	if (options.connection) {
		this.connection = options.connection;
		this.original_photo.before('<input id="photo_select_save" class="hide" type="button" value="Save"/>');
		this.save_button = jQ('#photo_select_save');
	}

	this.bind_clicks();

	var first_id = this.cat_select.children('option:first').val();
	this.get_category(first_id);
}

tb.photoselect.prototype.bind_clicks = function() {
	//bind cat_select clicks
	var ps = this;
	this.cat_select.change(function() {
		ps.get_category(this.value);
	});

	//finder
	this.finder.get(0).originalValue = this.finder.attr('value');
	this.finder.focus(function() {
		if (jQ(this).val() == this.originalValue) jQ(this).val('');
	}).blur(function() {
		if (jQ(this).val() == '') {
			jQ(this).val(this.originalValue);
			jQ(this).removeClass('search_pending');
			ps.find(false);
		}
	}).keypress(function(e) {
		if (e.keyCode == 13) {
			ps.find(jQ(this).val());
			jQ(this).removeClass('search_pending');
			return false;
		} else {
			if (!jQ(this).hasClass('search_pending')) jQ(this).addClass('search_pending');
		}
	});

	//bind live clicks to selectables
	jQ('.select_photo').live('click', function() {
		jQ('#photo_album .selected_photo').removeClass('selected_photo');
		jQ(this).addClass('selected_photo');
		var img = jQ(this).attr('title');
		var resize = '?'+ps.original_photo.attr('class').split('?')[1];
		if (ps.original_photo.is(':visible')) {
			ps.original_photo.hide().after('<div id="selected_image" style="height:120px;width:120px;background:transparent url('+img+resize+') no-repeat center center;"></div>');
		} else {
			jQ('#selected_image').css('background-image', 'url('+img+resize+')');
		}
		ps.hidden_thumb_input.attr('value', img.replace(CDN_BASE, ''));
		ps.input.attr('value', this.id);
		if (ps.connection) ps.save_button.show();
	});
	
	if (this.connection) {
		this.save_button.click(function() {
			var data = { cdn_url:jQ('#selected_image').attr('class'), id:this.photo_id_input.attr('value') };
			ps.connection.api.select(data);
		});
	}
}

tb.photoselect.prototype.get_category = function(cat_id) {
	this.photo_holder.html('<div id="cms_loading"></div>');
	this.finder.get(0).disabled = true;
	var ps = this;
	ONAPI.getPhotos({
		data: {user_id: user.id, cat_id: cat_id},
		callback: function(data) {
			ps.build_photo_select(data);
			ps.finder.get(0).removeAttribute('disabled');
			ps.find(false);
		},
		error: function(data) {
			//tb.purr({title:'Error getting Photo Album', message:'Details: '+data.error_message});
		}
	});
}

tb.photoselect.prototype.build_photo_select = function(data) {
	this.photo_holder.empty();
	var Photo = data;
	
	if (Photo.length == 0) {
		this.photo_holder.prepend('You have no photos in this category. Upload some in the the <a href="/photos">Photos Section</a>');
		return;
	}
	
	for (var i=0; i < Photo.length; i++) {
		var title = (Photo[i].name.length > 20) ? Photo[i].name.substr(0, 17)+'...' : Photo[i].name;
		this.photo_holder.append('<div class="select_photo" id="'+Photo[i].id+'" title="'+CDN_BASE+Photo[i].cdn_url+'"><div class="select_photo_img" style="background:transparent url('+CDN_BASE+Photo[i].cdn_url+'?h='+this.image_size+'&w='+this.image_size+') no-repeat center;height:'+this.image_size+'px;width:'+this.image_size+'px;"></div><div  class="select_photo_title">'+title+'</div></div>');
	}
}

tb.photoselect.prototype.find = function(value) {
	if (!value) {
		jQ('.select_photo').show();
		this.finder.attr('value', this.finder.get(0).originalValue);
		return;
	}

	jQ('.select_photo_title').each(function() {
		if (this.innerHTML.toLowerCase().match(value.toLowerCase())) {
			jQ(this).parent().show();
		} else {
			jQ(this).parent().hide();
		}
	});
	if (jQ('.select_photo:visible').length == 0) {
		jQ('.select_photo').show();
		this.finder.attr('value', this.finder.get(0).originalValue);
	}
}

tb.photoselectreceiver = function(options) {
	this.photo_id_input = jQ(options.photo_id_input);
	this.original_photo = jQ(options.original_photo);
}

tb.photoselectreceiver.prototype.select = function(data) {
	var id = data.id;
	var url = data.cdn_url;
	if (this.original_photo.is(':visible')) {
		this.original_photo.hide().after('<img id="selected_image" src="'+img+'">');
	} else {
		jQ('#selected_image').attr('src', img);
	}
	ps.input.attr('value', this.id);
}


//Content Chooser class
//Generic selection interface based on photoselect
//Supply a container (string of container id), content type (in the style of cms.section - products, photos, etc.)
//DBmodel (Photo, Product, Video, etc - if not in the cms), and onSelect callback to handle what you do with 
//a selected item.
tb.content_chooser = function(options) {
	this.defaults = {
		container: false, //id of container
		type: false, //content type for use with API calls
		DBmodel: false, //content type for items in json returned from API
		ignoreMultiModel: true, //for sections like products that have Product and ProductBundle, do not 
		thumb_height: 60,
		thumb_width: 60,
		onSelect: function() { alert('set the onSelect method for this content chooser'); }
	}
	//check for container
	if (options.container) {
		options.container = jQ('#'+options.container); //jquery select container
		if (!options.container.length) alert('Content chooser could not find provided container '+this.defaults.container);
		if (options.container.children('.content_items').length) return; //already a content chooser created.
	} else {
		alert('No container provided for content chooser.');
		return;
	}
	
	jQ.extend(this.defaults, options);
	jQ.extend(this, this.defaults);
	delete this.defaults;
	
	if (cms) {
		if (cms.section == this.type) { //fill with cat data
			this.generate(cms.cats);
		} else if (typeof(tb.content_chooser.loaded_content[this.type]) != 'undefined') { //use data already loaded by content_chooser
			this.generate(tb.content_chooser.loaded_content[this.type]);
		} else { //get data
			this.get_content();
		}
	}
}
//Get content, will use data store if content is already loaded
tb.content_chooser.prototype.get_content = function() {
	var CC = this;
	var id = (typeof(userId) == 'undefined') ? user.id : userId;
	ONAPI.request({
		data: { module: this.type, action: 'get', user_id: id },
		callback: function(data) {
			tb.content_chooser.loaded_content[CC.type] = data;
			CC.generate(data);
		}
	});
}
//Generate the selector
//c = content (cms.cats or data returned from API get)
tb.content_chooser.prototype.generate = function(c) {
	var CC = this;
	CC.content = c;
	var select = 'Category: <select>';
	var finder = '<input type="text" class="search_input" value="Search Category">';
	var content_items = '<div class="content_items">';
	var count = 0;
	for (var i in c) {
		var title = (typeof(c[i].name) == 'undefined') ? c[i].cat_title : c[i].name;
		select += '<option value="'+i+'">'+title+'</option>';
		if (!count) {
			content_items += CC.generate_category_items(i) + '</div>';
		}
		count++;
	}
	select += '</select>';
	
	//append generated markup and get components
	var o = CC.container.append(select+finder+content_items).children();
	CC.cat_select = jQ(o[0]);
	CC.finder = jQ(o[1]);
	CC.content_item_container = jQ(o[2]);
	
	//cat select
	CC.cat_select.change(function() {
		CC.content_item_container.html(CC.generate_category_items(this.value));
		CC.bind_item_clicks();
	});
	
	CC.bind_item_clicks();
	
	//finder
	CC.finder.get(0).originalValue = this.finder.attr('value');
	CC.finder.focus(function() {
		if (jQ(this).val() == this.originalValue) jQ(this).val('');
	}).blur(function() {
		if (jQ(this).val() == '') {
			jQ(this).val(this.originalValue);
			jQ(this).removeClass('search_pending');
			CC.find(false);
		}
	}).keypress(function(e) {
		if (e.keyCode == 13) {
			CC.find(jQ(this).val());
			jQ(this).removeClass('search_pending');
			return false;
		} else {
			if (!jQ(this).hasClass('search_pending')) jQ(this).addClass('search_pending');
		}
	});
}
//Show items from the selected category
tb.content_chooser.prototype.generate_category_items = function(c) {
	var CC = this;
	CC.selected_cat = c;
	var cat = CC.content[c];
	var items = (typeof(cat.items) == 'undefined') ? cat[CC.DBmodel] : cat.items;
	var content_items = '';
	for (var i in items) {
		if (CC.ignoreMultiModel && items[i].id.split('_').length > 1) {
		 //
		} else {
			var item = items[i];
			var title = (typeof(item.name) == 'undefined') ? item.item_title : item.name;
			content_items += '<div class="content_item" id="content_item_'+item.id+'">';
			//photos
			if (typeof(item.Photo) != 'undefined') { //for items with a linked photo
				if (item.Photo !== null) { //gotta check this exists too
					content_items += '<div class="content_item_thumb" style="background:transparent url('+CDN_BASE+item.Photo.cdn_url+'?h='+CC.thumb_height+'&w='+CC.thumb_width+') no-repeat center center;height:'+CC.thumb_height+'px;width:'+CC.thumb_width+'px;"></div>';
				}
			} else if (typeof(item.cdn_url) != 'undefined') { //for photos
				content_items += '<div class="content_item_thumb" style="background:transparent url('+CDN_BASE+item.cdn_url+'?h='+CC.thumb_height+'&w='+CC.thumb_width+') no-repeat center center;height:'+CC.thumb_height+'px;width:'+CC.thumb_width+'px;"></div>';
			}
			content_items += '<div class="content_item_title">'+title+'</div></div>';
		}
	}
	return content_items; //string of items for the content item div
}
//bind onSelect callback to the click event of each item showing
tb.content_chooser.prototype.bind_item_clicks = function() {
	var CC = this;
	//item select
	CC.container.find('.content_item').click(function() {
		//onSelect is defined in the options
		//argument is the item data
		var cat = CC.content[CC.selected_cat];
		var item = (typeof(cat.items) == 'undefined') ? cat[CC.DBmodel][this.id.split('_')[2]] : cat.items[this.id.split('_')[2]];
		CC.onSelect(item);
	});
}
//Search the selected category
tb.content_chooser.prototype.find = function(value) {
	var CC = this;
	
	if (!value) { //clear search, show all items
		jQ('.content_item').show();
		CC.finder.attr('value', CC.finder.get(0).originalValue);
		return;
	}
	
	value = value.toLowerCase();
	
	jQ('.content_item_title').each(function() { //search for a match
		if (this.innerHTML.toLowerCase().match(value)) { //found match
			jQ(this).parent().show();
		} else { //not a match
			jQ(this).parent().hide();
		}
	});
	
	if (!jQ('.content_item:visible').length) { //no matches, show all
		jQ('.content_item').show();
		CC.finder.attr('value', CC.finder.get(0).originalValue);
	}
}
//Content Chooser data store
tb.content_chooser.loaded_content = {};


/*
	Retrieves an object recursively from specific HTML markup.
	arg0 = id of container
*/
tb.getObjectFromDom = function(id, debug) {
	var o;
	var e = jQ('#'+id);
	if (!e.length) {
		cb.console('getObjectFromDom Fatal Error: No element exists with ID '+id);
		return;
	}
	if (typeof e.get(0).attributes['makeArray'] != 'undefined') {
		o = [];
	} else {
		o = {};
	}
	
	var E = 0; //error identifier
	debug = (typeof debug == 'undefined') ? false : debug; //mark searched areas with red border
	
	loop(e, o);
	
	return o;
	
	function loop(e, o) { //loop through .domObject children looking for more .domObject containers or .domObject value elements
		e.children().each(function() {
			//check elements without domObject class for nested domObject elements
			if (!jQ(this).hasClass('domObject')) { //element has no .domObject children
				cb.console('getObjectFromDom: element has no domObject children.');
				if (jQ(this).find('.domObject').length) { //.domObject descendants in the element
					cb.console('getObjectFromDom: element has domObject descendants.');
					if (debug) jQ(this).css('border', 'dotted 1px #f0f');
					loop(jQ(this), o); //descend into child and look for .domObject
				}
				return;
			}
			
			if (debug) jQ(this).css('border', 'solid 2px #f00');
		
			if (jQ(this).is('input.domObject, select.domObject, textarea.domObject')) { //found a value element
				if (o.constructor == Object) { //adding key and value to an object
					if (typeof this.attributes['domObjectKey'] != 'undefined') { //value element provides a key
						o[jQ(this).attr('domObjectKey')] = jQ(this).val();
					} else { //value element does not provide a key
						cb.console('getObjectFromDom Error '+E+': o.constructor is object but value element does not provide a key. See below.');
						cb.console(this);
						cb.console('getObjectFromDom Error '+E+': Ignoring value and continuing.');
						E++;
					}
				} else if (o.constructor == Array) { //adding value to indexed array
					o.push(jQ(this).val());
				}
			} else { //found a nesting element (creates new array or object)
				if (o.constructor == Object) { //using a key
					if (typeof this.attributes['domObjectKey'] != 'undefined') { //key is provided
						if (typeof this.attributes['makeArray'] != 'undefined') { //nested array requested
							o[jQ(this).attr('domObjectKey')] = [];
						} else { //nested object requested
							o[jQ(this).attr('domObjectKey')] = {};
						}
						loop(jQ(this), o[jQ(this).attr('domObjectKey')]);
					} else { //no key is provided
						cb.console('getObjectFromDom Error '+E+': o.constructor is object but nesting element does not provide a key. See below.');
						cb.console(this);
						cb.console('getObjectFromDom Error '+E+': Ignoring nesting element and continuing. Any data within will not be stored.');
						E++;
					}
				} else if (o.constructor == Array) { //push into array
					if (typeof this.attributes['makeArray'] != 'undefined') {
						o.push([]);
					} else {
						o.push({});
					}
					loop(jQ(this), o[o.length-1]);
				}
			}
		});
	}
}


tb.textselect = function(enable) {
	var Unselectable = {
		enable : function(e) {
			var e = e ? e : window.event;

			if (e.button != 1) {
				if (e.target) {
					var targer = e.target;
				} else if (e.srcElement) {
					var targer = e.srcElement;
				}

				var targetTag = targer.tagName.toLowerCase();
				if ((targetTag != 'input') && (targetTag != 'textarea') && (targetTag != 'select')) {
					return false;
				}
			}
		},
		disable : function () {
			return true;
		}
	}

	if (enable) {
		if (typeof(document.onselectstart) != 'undefined') {
			document.onselectstart = Unselectable.disable;
		} else {
			document.onmousedown = Unselectable.disable;
			document.onmouseup = Unselectable.disable;
		}
	} else {
		if (typeof(document.onselectstart) != 'undefined') {
			document.onselectstart = Unselectable.enable;
		} else {
			document.onmousedown = Unselectable.enable;
			document.onmouseup = Unselectable.disable;
		}
	}
}


/* JS Template Engine */
/*
function template(html, data){
	vars = html.split('{');
	for (var i=1;i<vars.length;i++) {
		var j = vars[i].split('}')[0];
		if(j.search("\\|") > 0) {
			//cb.console("GOT A PIPE! " + j);
			var o = j.split("|");
			var temp_j = "";
			for (var pos = 0; pos < o.length; pos++) {
				if(data[o[pos]]){
					temp_j = o[pos];
					//cb.console("(inside)J is " + temp_j);
					break;
				}
			}
			html = html.replace('{' + j + '}', data[temp_j]);
			//cb.console("(outisde)J is " + j);
		} else {
			html = html.replace('{'+j+'}', data[j]);
		}
	}
	return jQ(html);
}
*/
tb.template = {};   
tb.template.get = function(html, data){  
	vars = html.split('{');
	for (var i=1;i<vars.length;i++) { 
		var j = vars[i].split('}')[0]; //variable or variable with method attached
		var text;
		//check for use of a template method like truncate
		var jj = j.split('.');
		if (jj.length > 1) { //if a method is requested
			var v = jj[0]; //variable
			var method = jj[1].split('(');
			var m = method[0]; //method name 
			if (typeof(tb.template[m]) == 'function') { //if the method exists
				var args = method[1].replace(')','').split(',');
				args.unshift(data[v]); //add text to manipulate to the arguments
				text = tb.template[m].apply(this, args);
			} else {
				cb.console('tb.template: Error: method '+m+' does not exist');
				text = data[v];
			} 
		} else { //just got the variable name, grab it from data
			text = data[j];
		}
		html = html.replace('{'+j+'}', text);
	} 
	return jQ(html);
}
/*
 t = text from variable
 n = number of characters to show
 e = show elipses string
 */
tb.template.truncate = function(t, n, e) { 
	if (typeof(t) != 'string') {
		cb.console('tb.template.truncate: Error: no string given to truncate.');
		return '';
	}
	var num = parseInt(n); 
	if (num <= 0) {
		cb.console('tb.template.truncate: Error: length to truncate is <= 0. n = '+n);
		return t;
	}
	e = ((typeof(e) == 'string') ? ((e == 'true') ? '...' : '') : '');
	if (t.length > num) {
		return t.slice(0, num) + e; 
	} else {
		return t;
	}
}  

tb.validatePageUrl = function(url) { 
	return url.replace(userDomain, '').replace(/[^0-9a-zA-Z\-\_]/g,'');
}

function propCount(obj){
	var count = 0;
	for (i in obj) {
		count++;
	}
	return count;
}

function isEmpty(o){
   for(var i in o) { return false; }
  return true;
}

function callbackCounter(node, number, callback) {
	node.callbackCount = node.callbackCount + 1 || 1;
	//alert(node.callbackCount + ' of ' + number );
	if(node.callbackCount >= number) { callback(); }
}

// Dependancy Loader

function depLoad(list, callback, ignoreCache) {
	
	var ignoreCache = ignoreCache || false;
	var callback = callback || function(){};
	var n = 0;
	var loadCount = 0;
	var thisFunction = this;
	this.callbackCount = 0;
	
	if(ignoreCache == true) {
		var cacheStopper = '?' + Math.floor(Math.random()*1000001);
	} else {
		var cacheStopper = '';
	}
	
	loadCount = list.length;
	
	jQ.each(list, function() {
		
		n++;
		var currentFile = this + cacheStopper;
		
		ajaxWrapper(n, currentFile, loadCount);
		
		function ajaxWrapper(n, currentFile, loadCount) {
			
			
			jQ.get(currentFile, function(fileData) { 
			
				var fileName = currentFile;
								
				if( fileName.split('.')[fileName.split('.').length -1].match('js')) {
										
					var newElement = document.createElement('script');
					newElement.setAttribute("type","text/javascript");
					
					cb.appendScript(document.getElementsByTagName('head')[0], newElement);
					cb.setScriptHTML(newElement, fileData);
					
					

				} else if( fileName.split('.')[fileName.split('.').length -1].match('css') ) {
					
					var newElement=document.createElement("style");
					newElement.setAttribute("type", "text/css");
					
					cb.setStyleHTML(newElement, fileData);
					document.getElementsByTagName('head')[0].appendChild(newElement);
					
					
				}
				
				callbackCounter(document.body, loadCount, callback);
			
			});
		}	
				
	});
	
}

