(function($) {
	// static constructs
	$.tools = $.tools || {version: {}};

	$.tools.version.itinerary = '1.0';

	var current = null;

	// constructor
	function ITINERARY(source, conf) {
		// current instance
		var self = this;
		if(!current) { current = self; }

		// bind all callbacks from configuration
		$.each(conf, function(name, fn){
			if($.isFunction(fn)) {
				$(self).bind(name, fn);
			}
		});

		// Children
		var tagname;
		var https;
		var url_prefix;

		// Properties

		// Selection

		// Attributes

		/* ----------------- */
		/*   API Functions   */
		/* ----------------- */

		$.extend(self, {
			// Accessors
			getId: function() { return $(formtag).attr("id"); },
			getTagName: function() { return tagname; }
		});

		// Process Itinerary Add/Remove
		var process = function() {
			// Initialize Variables
			var link   = "";
			var params = "ajax=1";

			// Source Attr
			var flag        = parseInt($(source).attr("data-itinerary"));
			var detailslink = $(source).attr("data-detailslink");
			var itemtype    = $(source).attr("data-itemtype");
			var itemid      = $(source).attr("data-itemid");

			if(conf.remoteurl != "") {
				link = conf.remoteurl;
			} else {
				link = url_prefix + "://" + CGI["http_host"] + "/templates/itinerary/_remote/itinerary.cfm"
			}

			// Source Attributes are Required
			if(flag == "NaN" || typeof flag == "undefined") { return false; }
			if(detailslink == "undefined" || typeof detailslink == "undefined" || detailslink == "") { return false; }
			if(itemtype == "undefined" || typeof itemtype == "undefined" || itemtype == "") { return false; }
			if(itemid == "undefined" || typeof itemid == "undefined" || itemid == "") { return false; }

			// Get Mode
			var mode = (flag == 1) ? "delete" : "add";

			// Encode URI Form
			params = params + "&mode=" + mode + "&type=" + itemtype + "&id=" + itemid + "&link=" + escape(detailslink);

			$(source).attr("disabled","disabled");

			jQuery.post(link, params, function(results) {
				results = jQuery.trim(results);
				results = results.toLowerCase();

				if(results.indexOf("yes",0) > -1) {
					if(flag == 1) {
						if(conf.doswapstate == true) { swapstate("add"); }
						$(self).trigger("onRemove",source);
					} else {
						if(conf.doswapstate == true) { swapstate("remove"); }
						$(self).trigger("onAdd",source);
					}
				} else {
					alert("There was an error completing this operation. If this occurs frequently, please contact the site administrator.");
				}

				$(source).attr("disabled","");
			},"ajax");
		}

		// Swaps Itinerary State
		var swapstate = function(state) {
			var iflag    = 0;
			var itext    = "";
			var iclass   = "";
			var iimg     = "";
			var etrigger = true;

			if(arguments.length > 1 && arguments[1] == false) {
				etrigger = arguments[1];
			}

			if(state == "add") {
				iflag  = 0;
				itext  = conf.addtext;
				iclass = conf.addclass;
				iimg   = conf.addimg;
			} else {
				iflag  = 1;
				itext  = conf.removetext;
				iclass = conf.removeclass;
				iimg   = conf.removeimg;
			}

			$(source).attr("data-itinerary",iflag);
			$(source).attr("title",itext);
			$(source).removeClass(conf.addclass).removeClass(conf.removeclass).addClass(iclass);

			if(tagname == "img" && iimg != "") {
				$(source).attr("src",iimg);
			} else {
				if(($(source).html() != "" && $(source).html() != "&nbsp;") || conf.notextifblank == false) {
					$(source).html(itext);
				}
			}

			if(etrigger) { $(self).trigger("onStateSwap",source); }
		}

		// Initialize
		var init = function() {
			tagname = $(source)[0].nodeName.toLowerCase();

			// Default to Click Always
			if(conf.processevent == "") {
				conf.processevent = "click";
			}

			// Host and URL Info
			if(window.location.protocol == "https:") {
				https      = true;
				url_prefix = "https";
			} else {
				https      = false;
				url_prefix = "http";
			}

			// Add click functionality
			$(source).bind(conf.processevent, process);

			// show on init if this attribute is set to 1.
			if(parseInt($(source).attr("data-showoninit")) == 1) { $(source).show(); }

			// It should start on the proper state.
			if(conf.doswapstate == true) {
				if(parseInt($(source).attr("data-itinerary")) == 1) {
					swapstate("remove",false);
				} else {
					swapstate("add",false);
				}
			}

			$(self).trigger("onInit",source);
		}

		init();
	}

	// $ plugin implementation
	$.fn.itinerary = function(conf) {
		// already constructed --> return API
		var el = this.eq(typeof conf == 'number' ? conf : 0).data("itinerary");
		if(el) { return el; }

		var opts = {
			addtext: "Add To Itinerary",
			removetext: "Remove From Itinerary",
			addclass: "itinerary_add",
			removeclass: "itinerary_remove",
			addimg: "/templates/itinerary/images/add.gif",
			removeimg: "/templates/itinerary/images/remove.gif",

			// Change which event triggers the processing.
			processevent: "click",

			// Perform a state swap at all? Better have something in the events to handle if this is false.
			doswapstate: true,

			// If there is no text, it will never change it.
			notextifblank: true,

			 // Override the Remote URL. Ignores URL Prefix.
			remoteurl: "",

			// Events
			onAdd: function() { },
			onRemove: function() { },
			onStateSwap: function() { },
			onInit: function() { }
		};

		$.extend(opts, conf);

		this.each(function() {
			el = new ITINERARY($(this), opts);
			$(this).data("itinerary", el);
		});

		return opts.api ? el: this;
	};
})(jQuery);
