function synTabHandler(container) {
	var handler = this,
	    chosenClass = "chosen",
	    hiddenTabClass = "hiddenTab";
	this.container = $(container);
	this.contents = this.container.find(".synTabContents").children().filter("*").addClass("synTabContent");
	this.tabs = this.container.find(".synTabs").children().filter("*").addClass("synTab").click(function() {
		var tabIndex = handler.tabs.index(this);
		$(handler.tabs.removeClass(chosenClass)[tabIndex]).addClass(chosenClass);
		$(handler.contents.addClass(hiddenTabClass).hide()[tabIndex]).show().removeClass(hiddenTabClass);
	});

	this.tabs.find("a").click(function(event) {
		event.preventDefault();
	});

	if (this.tabs.length > 0)
		$(this.tabs[0]).click();
	this.container.data("synTabInitialized", true);
}
function synTabHandlerInitializeAll(context) {
	if (!window.synTabs) {
		window.synTabs = [];
	}
	window.synTabs.concat($(".synTabbed", context).map(function() {
		return !$(this).data("synTabInitialized") ? new synTabHandler(this) : null;
	}).get());
}
$(document).ready(function() {
	synTabHandlerInitializeAll();
});

$(document).ready(function() {
	if (!window.hs) return;

	hs.Expander.prototype.onBeforeExpand = function(sender) {
		synTabHandlerInitializeAll(this.content);
		$(this.content).
			find(".synTabContent").hide().end().
			find(".synTab:first").click();
		return true;
	};

	function showValues(container, item, keys) {
		var empty = [],
		    isNotEmpty = /[\w\d]/,
		    isHTML = /</;
		for (var i = 0, key; key = keys[i]; i++) {
			var target = container.find("." + key),
			    value = item[key],
			    valueTarget = target.find(".value");

			// no value... add to empty and skip to the next key
			if (!value || !isNotEmpty.test(value)) {
				target.hide();
				empty.push(key);
				continue;
			}

			// code to output Yahoo format price arrays
			if (value instanceof Array && (key === "price" || key === "salePrice")) {
				var str = "$" + value[0].toFixed(2);
				for (var j = 0, quantity, price; (quantity = value[++j]) && (price = value[++j]);)
					str += ", " + quantity + " for $" + price.toFixed(2);
				value = str;
			}

			// set the value in the valueTarget if any exist... else just fill the target itself
			if (valueTarget.length > 0) {
				if (isHTML.test(value)) {
					valueTarget.html(value);
				} else {
					valueTarget.text(value);
				}
			} else {
				if (isHTML.test(value)) {
					target.html(value);
				} else {
					target.text(value);
				}
			}

			target.not(".hiddenTab").show();
		}

		// tell the calling function which values are still unset
		return empty;
	}

	var hoverTarget,
	    popup = $(".bagItPopup"),
	    button = $("#bagItButton"),
	    buttonWidth = button.width(),
	    buttonHeight = button.height();

	// code to handle image hover
	if (button.is("img")) {
		var image = $(document.createElement("div")).css({
			"width": buttonWidth,
			"height": buttonHeight,
			"position": "relative"
		    }),
		    replacement = $(document.createElement("span")).
			attr({
				"id": button.attr("id"),
				"className": button.attr("class")
			}).
			css({
				"display": "inline-block",
				"width": buttonWidth,
				"height": buttonHeight = buttonHeight / 2,
				"overflow": "hidden"
			});

		// apply a PNG fix for IE6
		if ($.browser.msie && parseInt($.browser.version) <= 6 && /png$/i.test(button.attr("src"))) {
			image.css("filter", "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + button.attr("src") + "', sizingMethod='crop')");
		} else {
			image.css("background", "url(" + button.attr("src") + ")");
		}

		button.filter("#bagItButton[src$='png']").replaceWith(replacement.append(image));
		button = $("#bagItButton").
			mouseover(function(event) {
				image.css("top", -buttonHeight);
			}).
			mouseout(function(event) {
				image.css("top", 0);
			});
	}

	button.click(function() {
		button.hide();

		var clickTarget = $(hoverTarget),
		    itemId = clickTarget.attr("item");
		if (!itemId) {
			var href = clickTarget.parents("a").attr("href");
			if (href) {
				itemId = href.match(/([^\/\.]*)(\.html?)?$/);
				if (itemId) {
					itemId = itemId[1];
				} else {
					return;
				}
			}
		}

		var item = window.paging && paging.items ? paging.items[itemId] : {} || {},
		    popupId = "bagItPopup-" + itemId,
		    clone = $("#" + popupId),
		    values = ["name", "price", "salePrice", "description", "ingredients", "availability"],
		    emptyValues = null,
		    isXhrLoaded = false,
		    isImageLoaded = false,
		    showHighslideTimeout = null;
		if (clone.length === 0) {
			clone = popup.clone().attr("id", popupId);
			document.body.appendChild(clone[0]);
		}

		// initialize close button
		clone.find("a.highslide-close, .highslide-close a").click(function(event) {
			event.preventDefault();
			hs.close(this);
		});

		// initialize view product page
		clone.find("a.viewMore").attr("href", "#").click(function() { location.href = itemId + ".html"; return false; });

		// add order information to the form
		var form = clone.find("form[action*='//order.store.yahoo.net/'][action*='cgi-bin/wg-order']").
			append($(document.createElement("input")).attr({
				type: "hidden",
				name: "vwitem",
				value: itemId
			}));
		// add overlay and Floating Cart handler to form
		if (window.synFloatingCart && synFloatingCart.formHandler) {
			synFloatingCart.formHandler(form);
			form.submit(function() {
				$(window).one("synFloatingCart", function() {
					var expander = hs.getExpander(form[0]);
					if (expander) {
						// try to set the target of the closing animation to the
						//   floating cart display
						var duration = hs.restoreDuration,
						    steps = hs.restoreSteps,
						    cartDisplay = $(".synFloatingCart"),
						    position = cartDisplay.position(),
						    size = {
							width: cartDisplay.width(),
							height: cartDisplay.height()
						    };
						if (position) {
							if (expander.thumbLeft) {
								// highslide v3.3.9
								expander.thumbLeft = position.left;
								expander.thumbTop = position.top;
								expander.thumbWidth = size.width;
								expander.thumbHeight = size.height;
								hs.restoreSteps = 20;
							} else if (expander.x) {
								// highslide v4.0.8+
								expander.x.tpos = position.left;
								expander.y.tpos = position.top;
								expander.x.t = size.width;
								expander.y.t = size.height;
							}
							hs.restoreDuration = 500;
						}

						expander.close();
						hs.restoreDuration = duration;
						if (steps) {
							hs.restoreSteps = steps;
						}
					}
				});
			});
		}

		function showHighslide(force) {
			if ((isXhrLoaded && isImageLoaded) || force) {
				clearTimeout(showHighslideTimeout);
				$(".highslide-loading").css("top", -9999);
				hs.htmlExpand(hoverTarget, { "contentId": popupId, "outlineType": "bagIt" });
			} else {
				showHighslideTimeout = setTimeout(function() {
					showHighslide(true);
				}, 30000);
			}
		}

		// set information here
		emptyValues = showValues(clone, item, values);
		$.get(location.protocol + "//" + location.hostname + location.pathname.replace(/(\/[^\/]*)?$/, "/") + itemId + ".html", null, function(data) {
			// parse JSON
			var html = data,
			    jsonMarker = "<!--bagIt-json-start-->",
			    jsonStart = data.indexOf(jsonMarker),
			    jsonEnd = data.indexOf("<!--bagIt-json-end-->"),
			    json = (!(jsonStart < 0 || jsonEnd < 0)) ? data.substring(jsonStart + jsonMarker.length, jsonEnd) : null;
			    // json = data.match(/<!--bagIt-json-start-->((.|\n|\r)*)<!--bagIt-json-end-->/);
			try {
				if (json && (json = (window.JSON ? JSON.parse(json[1]) : eval("(" + json[1] + ")")))) {
					for (i in json) {
						// if new information is presented by the XHR request, display it over top of the information already in the item
						if (item[i]) emptyValues.push(i);

						item[i] = json[i];
					}
				}
			} catch (err) {
				if (window.console) console.log(err);
			}

			// push "json" onto the begining of the stack
			emptyValues.unshift("json");
			var valueKeys = data.match(/<!--bagIt-[^-]*(?=-start-->)/g);
			// then add all found valueKeys onto the emptyValues stack (except duplicates)
			if (valueKeys) {
				for (var i = 0, valueKey; valueKey = valueKeys[i]; i++) {
					valueKey = valueKey.substring("<!--bagIt-".length);
					if ($.inArray(valueKey, emptyValues) < 0)
						emptyValues.push(valueKey);
				}
			}
			// finally, remove "json" from the beginning of the stack again...
			emptyValues.shift();

			// process and display the rest of the keys in the stack
			$.each(emptyValues, function(key, value) {
				if (!item[value]) {
					var data = html, /* IE has mysteriously lost the data variable at this point in time and space... */
					    marker = "<!--bagIt-" + value + "-start-->",
					    start = html.indexOf(marker),
					    end = html.indexOf("<!--bagIt-" + value + "-end-->");
					if (!(start < 0 || end < 0)) {
						item[value] = html.substring(start + marker.length, end);
					}
					/* this code goes into a very slow loop in IE *after* it matches the regex... trying to determine why, but using a substring op for now
					var data = html,
					    regex = new RegExp("<!--bagIt-" + value + "-start-->((.|\n|\r)*)<!--bagIt-" + value + "-end-->", "g"),
					    matches = data.match(regex);
					item[value] = matches ? matches[1] : null;
					*/
				}
			});
			if (item.abstract) {
				var input = $(document.createElement("input")).attr({ name: "package", value: item.abstract, type: "hidden" }).get(0);
				input.value = item.abstract;
				clone.find("form").append(input);
			}
			showValues(clone, item, emptyValues);

			// calculate heights of all tabs
			clone.
				css({
					position: "absolute",
					left: "-3333em",
					display: "block"
				}).
				find(".synTabbed").each(function() {
					var tabContainer = $(this),
					    maxHeight = 0;
					tabContainer.find(".synTabContent").each(function() {
						var contents = $(this),
						    height = Math.max(contents.toggle().outerHeight(), contents.toggle().outerHeight());
						maxHeight = Math.max(maxHeight, height);
					});
					tabContainer.find(".synTabContents").css("height", maxHeight);
				}).end().
				css({
					left: 0
				});

			// try and show Highslide popup
			isXhrLoaded = true;
			showHighslide();
		});

		// preload product image
		var loadingAnimation = $(".highslide-loading"),
		    clickTargetPosition = clickTarget.offset();
		loadingAnimation.css({
			left: clickTargetPosition.left + ((clickTarget.width() - loadingAnimation.outerWidth()) / 2),
			top: clickTargetPosition.top + ((clickTarget.height() - loadingAnimation.outerHeight()) / 2)
		});
		var enlargedImage = $(document.createElement("img"));
		enlargedImage.load(function() {
				var existingImage = clone.find(".image img");
				if (existingImage.length === 0) {
					clone.find(".image").empty().append(enlargedImage);
				} else {
					existingImage.attr({
						src: enlargedImage.attr("src"),
						width: enlargedImage.attr("width"),
						height: enlargedImage.attr("height"),
						alt: enlargedImage.attr("alt")
					});
				}
				// try and show Highslide popup
				isImageLoaded = true;
				showHighslide();
			}).
			attr({
				src: clickTarget.attr("lrgsrc") || clickTarget.attr("src"),
				alt: item.name
			});
	});

	$(".bagIt img").
		mouseover(function() {
			var image = $(this),
			    position = image.offset();

			button.css({
				left: position.left + ((image.width() - buttonWidth) / 2),
				top: position.top + ((image.height() - buttonHeight) / 2)
			}).show();

			hoverTarget = this;
		}).
		mouseout(function(e) {
			// this code has thrown errors with a e.relatedTarget of "div.anonymous-div"
			try {
				if (e.relatedTarget && !(e.relatedTarget === button[0] || e.relatedTarget.parentNode === button[0])) {
					button.hide();
				};
			} catch (err) {
				if (window.console) console.log(err);
			}
		});
});

