var THUMBNAILS_OPACITY = 0.4;
var EXPANDED_COL_WIDTH = '62%';
var COLLAPSED_COL_WIDTH = '19%';
var DEFAULT_COL_WIDTH = '33%';
var MINIMUM_DESCRIPTION_HEIGHT = 40;
var PRODUCT_INFO_HEIGHT = 140; // 140 - height of the preview, minus paddings
var ANIMATION_SPEED = 2; // Bigger is slower and smoother :)
var ANIMATION_DELAY = 25; // Again: bigger is slower and smoother :)

var isAnythingMoving = false;
var default_product_width;
var previousRow;
var products = [];

	String.prototype.reverse = function() {
		// gnirts eht esrever noitcnuf sihT
		var s = "";
		var i = this.length;
		while (i>0) {
			s += this.substring(i-1,i);
			i--;
		}
		return s;
	}

	String.prototype.str_replace = function(search, replace) {
		return this.split(search).join(replace);
	}

	String.prototype.reverseIndexOf = function(needle, offset) {
		// Same as indexOf (aka strpos) but in the reverse dirrection (starting from offset)
		var index = this.reverse().indexOf(needle, this.length - offset);
		return this.length - index;
	}

	String.prototype.trim = function(chars) {
		// Trims whitespace (plus additional chars if set) from string
		re = new RegExp("(^[\\s"+chars+"]+)|([\\s"+chars+"]+$)", "g");
		return this.replace(re, "");
	}

	jQuery.fn.equalizeCols = function() {

		jQuery(this).filter(function() {
			return jQuery(this).find(".auto_fill").length == 0;
		}).each(function() {
			jQuery(this).prepend(jQuery("<div class='auto_fill'></div>").height(0));
		}).css("height", "auto");

		var max_height= 0;

		jQuery(this).each(function() {
			var self= jQuery(this);
			var height= self.height() - self.find(".auto_fill").height();
			max_height=height > max_height ? height : max_height;
		});

		jQuery(this).each(function() {
			var self= jQuery(this);
			var height= self.height() - self.find(".auto_fill").height();
			self.find(".auto_fill").height(max_height - height).css('font-size', 0);
		});
	}

function getExponentialStep(value, desiredValue) {
	var difference = Math.max(value, desiredValue) - Math.min(value, desiredValue);
	step = 0;
	if (difference >= 2) {
		step = (desiredValue - value) / ANIMATION_SPEED;
	}
	return step;
}

function finalizeClassesOnStop(element) {
	if (element.className.indexOf('collapsing') > 0) {
		element.className = element.className.replace(" collapsing", "") + " collapsed";
	} else if (element.className.indexOf('expanding') > 0) {
		element.className = element.className.replace(" expanding", "") + " expanded";
	}
}

function startMoving() {

	if (!isAnythingMoving) {
		// Just started, need to close variant's select (if any opened)
		$("select").blur();
	}

	isAnythingMoving = true;

	if (window.products.length == 0) {
		var container = document.getElementById('products');
		var products1 = container.getElementsByTagName('DIV');
		for (i in products1) {
			element = products1[i];
			if (!element || !element.className || element.className.indexOf('product') == -1) {
				continue;
			}
			window.products[window.products.length] = element;
		}
	}

	var busyElements = 0;

	for (i in window.products) {
		element = window.products[i];

		desiredLeft = element.getAttribute('desiredLeft');
		if (desiredLeft == '') {
			finalizeClassesOnStop(element);
			continue;
		}

		fDesiredLeft = parseFloat(desiredLeft);

		var left = element.style.left;
		fLeft = parseFloat(left);

		if (!fLeft) {
			fLeft = element.getAttribute("defaultLeft");
		}

		var step = getExponentialStep(fLeft, fDesiredLeft);

		if (step != 0) {
			busyElements++;
			element.style.left = Number(fLeft) + Number(step) + "px";
		} else {
			element.style.left = desiredLeft;
			element.setAttribute("desiredLeft", "");

			finalizeClassesOnStop(element);

			// If unsupported variant was chosen - switch to default (attractive) variant
			if ($(".noprice:visible", element).length) {
				$("form", element).get(0).reset();
				$("form .variant_switcher", element).change();
			}

		}

	}

	if (busyElements > 0) {
		setTimeout(startMoving, ANIMATION_DELAY);
	} else {
		isAnythingMoving = false;
	}

}

function restoreOriginalState(product) {
	if (!product) {
		product = $("#products .product");
	}
	$(product).removeClass("collapsed").removeClass("expanded").each(function(){
		$(this).attr('desiredLeft', $(this).attr('defaultLeft'));
		$(".thumbnails", this).shadow();
		$(".info", this).animate({
			marginLeft: "160px"
		}, ANIMATION_SPEED*100);
		$(".preview", this).animate({
			width: "140px"
		}, ANIMATION_SPEED*200);
	});
	previousRow = null;
	startMoving();
}

	$.fn.shadow = function() {
		return $(this)
		.animate({
			opacity: THUMBNAILS_OPACITY
		}, ANIMATION_SPEED*100)
		.data("shadowed", 1);
	}

	$.fn.reveal = function() {
		return $(this)
		.animate({
			opacity: 1
		}, 600)
		.data("shadowed", 0);
	}

	$.fn.count = function() {
		var result = 0;
		for (var i in this.get(0)) {
			result++;
		}
		return result;
	}

function expandProduct(element) {

	$(element).parents(".row").add(previousRow).each(function(){

		var left = 0;

		$(".product", this).each(function(){

			var desiredWidth = parseFloat(DEFAULT_COL_WIDTH);

			if (this != element) {
				$(".thumbnails", this).shadow();
				$(".info", this).animate({
					marginLeft: "160px"
				}, ANIMATION_SPEED*100);
			}

			if (this == element) {

				previousRow = this.parentNode;

				// To be expanded ~60% width
				$(".thumbnails", this).reveal();
				$(".info", this).animate({
					marginLeft: 0
				}, ANIMATION_SPEED*100);
				$(this).removeClass("collapsing").addClass('expanding');
				desiredWidth = parseFloat(EXPANDED_COL_WIDTH);

			} else if (this.parentNode == element.parentNode) {
				// To be collapsed to ~20% width
				$(this).removeClass("expanding").addClass('collapsing');
				desiredWidth = parseFloat(COLLAPSED_COL_WIDTH);
			} else {
				// To be collapsed to ~33% width
				$(this).removeClass("expanding").addClass("collapsing");
			}

			if (this.parentNode == element.parentNode) {
				$(".preview", this).animate({
					width: "95px"
				}, ANIMATION_SPEED*200);
			} else {
				$(".preview", this).animate({
					width: "140px"
				}, ANIMATION_SPEED*200);
			}

			$(this).removeClass("expanded").removeClass("collapsed");

			desiredWidth = row_width * desiredWidth / 100;
			$(this).attr('desiredLeft', left);
			$(this).attr('desiredWidth', desiredWidth);
			left += desiredWidth;

		});


	});

	if (!isAnythingMoving) {
		startMoving();
	}

}

function getProductFooter(product, variant_id) {
	var footer;
	var price_block = $("#variant_" + variant_id, product);
	var product_variants = allVariants[product.attr("product_id")];
	if (!product_variants) return null;
	var product_variants_count = $(product_variants).count();
	if (price_block.length == 0) {
		var variant_data = product_variants[variant_id];
		if (variant_data) {
			button_tpl_id = "info_button_block";
			if (variant_data.is_purchasable) {
				button_tpl_id = "buy_button_block";
			}
			button_tpl = $("#" + button_tpl_id).html();
			template_id = "#product_footer";
			if (variant_data["price_negotiated"]) {
				template_id = "#product_negotiatable_footer";
			}
			footer = $(template_id).clone();
			//filling with data
			$(".controls", footer).html(button_tpl);
			$(".from", footer).html((product_variants_count > 1 && variant_data["is_attractive"]) ? I18N_TEXT_FROM : "");
			$(".prices", footer).html(variant_data["price"]);
			$(".stock", footer).html(variant_data["stock"]);
			$(".product_url", footer).attr("href", product.attr("href"));
		} else {
			footer = $("#product_unavailable").clone();
		}
		$(".block_id", footer).attr("id", "variant_" + variant_id);
		if ("not sovled http://dev.jquery.com/ticket/4691") {
			// we need to just change a name of a button, but as it doesn't work in IE we recreate full button
			button = $(".buy_button", footer);
			if (button.attr("src")) {
				$(".buy_button", footer).replaceWith("<input type='image' src='"+button.attr("src")+"' alt='"+button.attr("alt")+"' name=\""+'variants_values['+variant_id+']'+"\">")
			} else {
				$(".buy_button", footer).replaceWith("<button class=\"button\" type='submit' name=\""+'variants_values['+variant_id+']'+"\">" + button.html()
					+ "</button>");

			}
			qty = $(".qty_field", footer);
			$(".qty_field", footer).replaceWith("<input type='text' size=3 value=1 name='product_qty["+variant_id+"]'>");
		}
		footer_html = footer.html();
		$(".footer", product).prepend(footer_html);
		price_block = $("#variant_" + variant_id, product);
	}
	return price_block;
}


$().ready(function(){

	$("td.manufacturer").each(function(){
		// Fixing rare IE6 weird zero width of <td> with dropdown (see #2417 note ~6126)
		if ($(this).width() < 10) {
			$(this).width(200);
		}
	});

	row_width = $("#products").width();
	expanded_product_width = row_width * parseFloat(EXPANDED_COL_WIDTH) / 100;

	$(".row").each(function(){
		$(".title h2", this).equalizeCols();
	});


	$(".thumbnails").each(function(){
		$("img:first", this).addClass("selected");
	});

	$("#products .product").mouseover(function(){
		if (!$(this).hasClass("expanded") && !$(this).hasClass("expanding")) {
			var product = this;
			$(".preview a", product).click(function(){
				$(this).unbind("click"); // 2nd click must open Product Info page
				expandProduct(product);
				return false;
			});
		}
	});

	$("#products .product").each(function(){
		var product_id = this.id.str_replace('product_', '');
		$(this).attr("product_id", product_id);
		$(this).attr("href", $(".url", this).attr("href"));
	});

	// Adding footer for each product (stock, price, buy/info button)
	$("#products .product").each(function(){
		var product_id = $(this).attr("product_id");
		var product_variants = allVariants[product_id];
		// First element is the most attractive one
		attractive_variant_id = 0;
		count = 0;
		for (var i in product_variants) { // how correctly to get the first one???
			count++;
			if (!attractive_variant_id)
				if (product_variants[i].is_attractive)
					attractive_variant_id = i;
		}
		// Delete old footer (generated on server)
		$(".footer", this).empty();
		// Create first advanced footer
		getProductFooter($(this), attractive_variant_id);
	});

	// Adding dropdowns for variants.
	// Must be added before optimizing description height (so dropdowns height could be excluded)
	$("#products .product").each(function(){
		var product_id = $(this).attr("product_id");
		var attributes = allAttributes[product_id];
		if (!attributes) {
			// There are no variants
			return;
		}
		html = '\n<table>';
		for (var i in attributes) {
			title = i;
			values = attributes[i];
			if (values.length == 1) {
				// When only one color - just print it, not in dropdown
				html += '<tr><td>'+title+'</td><td width="60%">' + values[0].value + '<input class="variant_switcher" type="hidden" value="'+values[0].vvid+'"></td></tr>';
			} else {
				html += '<tr><td>'+title+'</td><td width="60%">\n<select class="variant_switcher">\n';
				for (var j in values) {
					html += '<option value="'+values[j].vvid+'"' + (values[j].is_attractive ? ' selected="selected" ' : '') + '>'+ values[j].value+'</option>\n';
				}
				html += '</select></td></tr>';
			}
		}
		html += '</table>\n\n';
		$('.variants', this).html(html);
	});

	$("#products .product").each(function(){
		// Fixing width of the info box (before it will be cut in height)
		$(".data .info", this).width(expanded_product_width - 165); // TODO: Remove hard-code. 165 is a rest space: width of preview + width of smaller preview + all paddings.
	});

	// Making optimum height for description and variants of products.
	// Let description text fill every space which left from variants selectboxes
	$("#products .product").each(function(){

		var more_link = $(".info .more", this);
		var more_text = more_link.html();
		more_link.empty();

		var current_height, desired_height;

		current_height = $(".description", this).height();
		desired_height = Math.max(MINIMUM_DESCRIPTION_HEIGHT, PRODUCT_INFO_HEIGHT - $(".variants", this).height());

		element = $(".description", this);
		text = element.text();

		if (current_height > desired_height) {

			var difference = desired_height / current_height;
			position = text.reverseIndexOf(" ", (text.length * difference)); // trimmming to first space before cut position
			if (position > 0) {
				text = text.substr(0, position);
			}
			element.height("auto");

		} else if (desired_height - current_height < 20) {
			// If tnot very big difference (line or two) - let it go :) (besides "more info" link may give this extra line)
			element.height("auto");
		} else {
			// If it's almoust empty - fill the rest space with nothing, so selectboxes will be still alligned to the bottom
			element.height(desired_height);
		}

		element.html(text.trim('.') + "&hellip;<br>" + more_text);

		$(this).attr("defaultLeft", this.offsetLeft);

	});

	// Preparing products to be animated when needed
	// Nailing them to the absolute coordinates, freezing heights
	var defaultWidth = row_width * parseFloat(DEFAULT_COL_WIDTH) / 100;
	$("div.row").each(function(){
		var left = 0;
		$(this).css({
			height: $(this).height() + "px"
		});
		$(".product", this).each(function(){
			$(this).attr("defaultLeft", left);
			$(this).attr("defaultWidth", defaultWidth);
			$(this).attr("desiredLeft", "");
			$(this).css({
				left: left + "px",
				position: "absolute",
				width: parseInt(expanded_product_width) + "px"
			});
			left += defaultWidth;
		});
	});

	// Switching preview when hovering the thumbnail
	$(".thumbnails img").mouseover(function(){
		$("img", $(this).parent()).not(this).removeClass("selected");
		$(this).addClass("selected");
		$(".preview img:first", $(this).parents('.product')).attr('src', $(this).attr('longdesc')); // only the 1st image is a preview, there's also a "expand me" button
	});

	$(".product .close a").click(function(){
		restoreOriginalState();
		return false;
	});

	// Changing price when switching another variant
	$(".variant_switcher").change(function(){
		product = $(this).parents('.product');
		var price_block_id = $(this).parents(".product").attr("product_id");
		$(".variant_switcher", product).each(function(){
			price_block_id += '_' + this.value;
		});
		variant_id = revAttributes[price_block_id];
		price_block = getProductFooter(product, variant_id).hide();

		// Doing change effect
		$(".footer > *", product).not(price_block).slideUp('slow'); // Hiding old
		price_block.slideDown("slow"); // Showing new

	});

});
