(function($) {

	/*---------------------------------------------------------------------
	 * CONSTANTS
	 *--------------------------------------------------------------------*/

	$.daniel = {

		utils : {

			slugfy : function(value) {

				var slug = value;

				var replace = function(string, key, value) {

					while (string.indexOf(key) >= 0) {

						string = string.replace(key, value);
					}

					return string;
				};

				slug = replace(slug, " ", "-");
				slug = replace(slug, "?", "");
				slug = replace(slug, ",", "");
				slug = replace(slug, ",", "");
				slug = replace(slug, ".", "");
				slug = replace(slug, "'", "");
				slug = replace(slug, "\n", "-");
				slug = replace(slug, "--", "-");
				slug = slug.toLowerCase();

				return slug;
			},

			pad : function(length) {

				if (length) {

					return length >= 10 ? length : ("0" + length);
				}

				return "";
			},

			endsWith : function(string, value) {

				var index = string.indexOf(value);
				var position = string.length - value.length;

				return index == position;
			},

			getRelativeUrl : function(value, url) {

				url = url || window.location.href;

				var paths = value.split("../");

				for ( var i = 0; i < paths.length; i++) {

					var path = paths[i];

					if (path) {

						url += "/" + path;
					} else {

						url = url.substring(0, url.lastIndexOf("/"));
					}
				}

				return url;
			},

			center : function(element, parent, horizontal, vertical) {

				horizontal = typeof horizontal == "boolean" ? horizontal : true;
				vertical = typeof vertical == "boolean" ? vertical : true;

				var props = {};

				if (horizontal) {
					props.left = (parent.width() / 2) - (element.width() / 2);
				}

				if (vertical) {
					props.top = (parent.height() / 2) - (element.height() / 2);
				}

				element.css(props);
			}
		}
	};

	/*---------------------------------------------------------------------
	 * END OF CONSTANTS
	 *--------------------------------------------------------------------*/

	/*---------------------------------------------------------------------
	 * CLASSES
	 *--------------------------------------------------------------------*/

	/*---------------------------------------------------------------------
	 * END OF CLASSES
	 *--------------------------------------------------------------------*/

	/*---------------------------------------------------------------------
	 * JQUERY PLUGINS
	 *--------------------------------------------------------------------*/

	/**
	 * jQuery plugin that helps reading and writing data from HTML forms to JS
	 * Hash objects and vice-versa.
	 * 
	 * @param value
	 *            the hash of properties being written to the fields of the form
	 *            mapped by this jQuery object (ignored while reading).
	 * 
	 * @return jQuery instance while writing and read data hash object while
	 *         reading
	 */
	$.fn.formdata = function(value) {

		if (typeof value == "undefined") {

			var widgets = this.find(":input");
			var fields = widgets.serializeArray();

			var data = {};

			for ( var i = 0; i < fields.length; i++) {

				var field = fields[i];

				var name = field.name;
				var value = field.value;

				data[name] = value;
			}

			return data;
		}

		return this;
	};

	$.fn.reset = function() {

		var fields = this.find(':input').not(
				':button, :submit, :reset, :hidden');

		fields.val('').removeAttr('checked').removeAttr('selected');

		this.find(".errorlist").hide();

		return this;
	};

	$.fn.form = function(callback, submitCallback) {

		var self = this;

		this.submit(function() {

			var url = self.attr("action");
			var data = self.formdata();

			if (submitCallback) {
				submitCallback.apply(self);
			}

			$.post(url, data, function(response) {

				var form = $(response);

				if (!form.is("form")) {

					form.find("form")
				}

				self.html(form.html());

				var errors = self.find(".errorlist:first");

				errors.parent().find(":input:first").focus();

				if (callback) {
					callback.apply(self, [ errors.length > 0 ]);
				}

			});

			return false;
		});
	};

	$.fn.refresh = function(url, data, callback) {

		var self = this;

		data = data || {};

		data.wrap = true;

		$.get(url, data, function(response) {

			var content = $("<div />");

			content.html(response);

			var selector = "[class=" + self.attr("class") + "]";

			if (!content.is(selector)) {
				content = content.find(selector);
			}

			self.html(content.html());

			if (callback) {
				callback.apply(self);
			}
		});
	};

	$.fn.cancel = function(callback) {

		var self = this;

		this.keydown(function(e) {

			if (e.keyCode == 27) {

				callback.call(self);
			}
		});
	};

	$.fn.slugfy = function(target) {

		var self = this;

		self.keyup(function() {

			target.val($.daniel.utils.slugfy(self.val()));
		});

		self.attr("autocomplete", "off");
		target.attr("autocomplete", "off");
	};

	$.fn.generateId = function(prefix) {

		var id = Math.random().toFixed(10).substring(2);

		if (prefix) {

			id = prefix + id;

			this.attr("id", id);
		}

		return id;
	};

	$.fn.center = function(horizontal, vertical) {

		this.each(function() {

			var element = $(this);
			var parent = element.parent();

			$.daniel.utils.center(element, parent, horizontal, vertical)
		});
	};

	$.fn.flowplayer = function(lazy, allControls) {

		var self = this;
		var url = "http://releases.flowplayer.org/swf/flowplayer.commercial-3.2.7.swf";
		var controls = "http://releases.flowplayer.org/flowplayer.controls/flowplayer.controls-3.2.7.swf";

		var install = function() {

			var id = self.generateId("player");

			var player = flowplayer(id, {
				src : url,
				wmode : 'opaque'
			}, {
				key : "#$b08d6f67d9dc74a1e6c",
				clip : {
					autoPlay : false,
					autoBuffering : true
				},
				"screen" : {
					"height" : "100pct",
					"top" : 0
				},
				plugins : {
					controls : {
						url : controls,
						volume : allControls === true,
						time : allControls === true,

						"borderRadius" : "0px",
						"buttonOffColor" : "rgba(130,130,130,1)",
						"timeColor" : "#ffffff",
						"stop" : false,
						"bufferGradient" : "none",
						"sliderColor" : "#000000",
						"zIndex" : 1,
						"backgroundColor" : "rgba(0, 0, 0, 0)",
						"scrubberHeightRatio" : 0.6,
						"volumeSliderGradient" : "none",
						"tooltipTextColor" : "#ffffff",
						"spacing" : {
							"time" : 6,
							"volume" : 8,
							"all" : 2
						},
						"sliderGradient" : "none",
						"timeBorderRadius" : 20,
						"timeBgHeightRatio" : 0.8,
						"volumeSliderHeightRatio" : 0.6,
						"progressGradient" : "none",
						"height" : 26,
						"volumeColor" : "rgba(153, 153, 153, 1)",
						"timeSeparator" : " ",
						"tooltips" : {
							"marginBottom" : 5,
							"buttons" : false
						},
						"name" : "controls",
						"volumeBarHeightRatio" : 0.2,
						"opacity" : 1,
						"left" : "50pct",
						"timeFontSize" : 12,
						"tooltipColor" : "rgba(0, 0, 0, 0)",
						"bufferColor" : "rgba(153, 153, 153, 1)",
						"volumeSliderColor" : "#ffffff",
						"border" : "0px",
						"buttonColor" : "rgba(255, 255, 255, 1)",
						"durationColor" : "rgba(153, 153, 153, 1)",
						"autoHide" : {
							"enabled" : true,
							"hideDelay" : 500,
							"hideStyle" : "fade",
							"mouseOutDelay" : 500,
							"hideDuration" : 400,
							"fullscreenOnly" : false
						},
						"backgroundGradient" : "none",
						"width" : "100pct",
						"sliderBorder" : "1px solid rgba(128, 128, 128, 0.7)",
						"display" : "block",
						"buttonOverColor" : "#ffffff",
						"url" : "flowplayer.controls-3.2.5.swf",
						"progressColor" : "rgba(153, 153, 153, 1)",
						"timeBorder" : "0px solid rgba(0, 0, 0, 0.3)",
						"timeBgColor" : "rgb(0, 0, 0, 0)",
						"scrubberBarHeightRatio" : 0.2,
						"bottom" : 0,
						"volumeBorder" : "1px solid rgba(128, 128, 128, 0.7)",
						"builtIn" : false,
						"margins" : [ 2, 12, 2, 12 ]
					}
				}
			});

			player.onFinish(function() {

				player.stop();
//				setTimeout(function() {
//					self.children().empty();
//					install();
//
//				}, 1000);
			});

			var android = /Android/i.test(navigator.userAgent);

			player.ipad({
				simulateiDevice : android
			});
		};

		if (lazy === false) {

			install();

		} else {

			self.click(function() {

				install();

				return false;
			});
		}
	};

	$.fn.texteditor = function(callback) {

		var settings = {

			// Location of TinyMCE script
			script_url : $.daniel.urls.media + 'common/js/mce/tiny_mce.js',

			// General options
			theme : "advanced",

			plugins : "spellchecker,pagebreak,style,layer,table,save,advhr,advimage,advlink,emotions,iespell,inlinepopups,insertdatetime,preview,media,searchreplace,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras,template",

			// Theme options
			theme_advanced_buttons1 : "save,newdocument,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect,fontselect,fontsizeselect",
			theme_advanced_buttons2 : "cut,copy,paste,pastetext,pasteword,|,search,replace,|,bullist,numlist,|,outdent,indent,blockquote,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code,|,insertdate,inserttime,preview,|,forecolor,backcolor",
			// theme_advanced_buttons3 :
			// "tablecontrols,|,hr,removeformat,visualaid,|,sub,sup,|,charmap,emotions,iespell,media,advhr,|,print,|,ltr,rtl,|,fullscreen",
			// theme_advanced_buttons4 :
			// "insertlayer,moveforward,movebackward,absolute,|,styleprops,spellchecker,|,cite,abbr,acronym,del,ins,attribs,|,visualchars,nonbreaking,template,blockquote,pagebreak,|,insertfile,insertimage",
			theme_advanced_toolbar_location : "top",
			theme_advanced_toolbar_align : "left",

			width : 700,
			height : 400,

			// Example content CSS (should be your site CSS)
			/* content_css : "css/content.css", */

			// Drop lists for link/image/media/template dialogs
			// template_external_list_url : "lists/template_list.js",
			// external_link_list_url : "lists/link_list.js",
			// external_image_list_url : "lists/image_list.js",
			// media_external_list_url : "lists/media_list.js",
			// Replace values for the template plugin
			// template_replace_values : {
			// username : "Some User",
			// staffid : "991234"
			// },
			relative_urls : false,

			script_loaded : function() {

				// give it some time to initialize and then invoke callback
				setTimeout(function() {

					if (callback) {
						callback.call();
					}
				}, 500);
			}
		};

		this.tinymce(settings);
	};

	$.fn.reverseOrder = function() {

		return this.each(function() {
			$(this).prependTo($(this).parent());
		});
	};

	/**
	 * Simple plug-in that helps us track the mouse down event within a series
	 * of elements by adding the class "down" when while the mouse is down, and
	 * removing the same when the mouse leaves/up the element.
	 * 
	 * <p>
	 * This is helpful if you need to change the css state of buttons for
	 * example.
	 * </p>
	 * 
	 * @return this jQuery stack object
	 */
	$.fn.trackMouseDown = function() {

		this.each(function() {

			var item = $(this);

			var mouseDownHandler = function() {

				var asset = $(this);

				asset.addClass("down");
			};

			var mouseUpHandler = function() {

				var asset = $(this);

				asset.removeClass("down");
			};

			var mouseOutHandler = function() {

				var asset = $(this);

				asset.removeClass("down");
			};

			/*
			 * handlers used to add down class when mouse is down and to remove
			 * it when up
			 */
			item.mousedown(mouseDownHandler);
			item.mouseup(mouseUpHandler);
			item.mouseout(mouseOutHandler);
		});

		return this;
	};

	/*---------------------------------------------------------------------
	 * END OF JQUERY PLUGINS
	 *--------------------------------------------------------------------*/

	/*----------------------------------------------------------
	 * OVERRIDDEN CLASSES
	 *----------------------------------------------------------*/

	/*
	 * Add support to indexOf for IE
	 */
	if (!Array.indexOf) {

		Array.prototype.indexOf = function(obj, start) {

			for ( var i = (start || 0); i < this.length; i++) {
				if (this[i] == obj) {
					return i;
				}
			}

			return -1;
		};
	}

	/*----------------------------------------------------------
	 * END OF OVERRIDDEN CLASSES
	 *----------------------------------------------------------*/

})(jQuery);

