// *****************************************************************************
// UserPage Class
// *****************************************************************************

/**
 * @class UserPage
 * @constructor
 * @description Provides client side behavior for pcthandbook.com's user page
 */

var UserPage = function() {

	// Element handles
	this.shoppingCart = null;
	this.shoppingCartLabel = null;
	this.shoppingCartDetails = null;
	
	this.addToCartStatus = {};

	// Data elements
	this.cart = null;
	this.destinationId = null;
	this.postage = null;

}; // end UserPage class



// *****************************************************************************
// Behavior
// *****************************************************************************

UserPage.prototype.behavior = function(bCart) {

	// Save a reference for later use by closures
	var that = this;

	if (bCart == true) {

		//
		// Cart behavior
		// 	

		$("#shoppingCartDetails #selectShipping").unbind("change").bind("change", function(e) { that.selectShipping_change(e); });
		$("#shoppingCartDetails a.updateLink").unbind("click").bind("click", function(e) { that.updateLink_click(e); });
		$("#shoppingCartDetails a.removeLink").unbind("click").bind("click", function(e) { that.removeLink_click(e); });
		$("#shoppingCartDetails #checkOutLink").unbind("click").bind("click", function(e) { that.checkOutLink_click(e); });
	}
	else {

		//
		// General behavior
		// 	

		$("img.closeUp").unbind("click").bind("click", function(e) { that.imgCloseUp_click(e); });		
		$("a.closeLink").unbind("click").bind("click", function(e) { that.closeLink_click(e); });		
		$("a.addToCartLink").unbind("click").bind("click", function(e) { that.addToCart_click(e); });
		$("a.viewCartLink").unbind("click").bind("click", function(e) { that.viewCart_click(e); });
		$("a.hideCartLink").unbind("click").bind("click", function(e) { that.hideCart_click(e); });
	}

}; // end UserPage.behavior()


// *****************************************************************************
// Event Handling methods
// *****************************************************************************

/**
 * @description Initialization method run on document ready
 */

UserPage.prototype.init = function() {

	//
	// 1) Get element handles
	//

	this.shoppingCart = $("div#shoppingCart");
	this.shoppingCartLabel = $("div#shoppingCart p");
	this.shoppingCartDetails = $("#shoppingCartDetails");

	//
	// 2) Get Data
	//

	try { 
		this.cart = gCart; 
	}
	catch (exp) { 
		this.cart = null; 
	}

	try { 
		this.destinationId = Number(gDestinationId); 
	}
	catch (exp) { 
		this.destinationId = 1; // 1 = USA, 2 = CAN, 3 = INTL 
	}

	try { 
		this.postage = gPostage; 
	}
	catch (exp) { 
		this.postage = null; 
	}
	
	//
	// 3) Apply behavior
	//

	this.behavior();

	//
	// 4) Set the email address anchor element
	//

	var mailto = ["ma", "i", "lto", ":", "yo", "gi", "hik", "es", "@g", "ma", "i", "l", ".", "co", "m"];
	var aEmailLink = $("a#emailLink");
	$(aEmailLink).attr("href", mailto.join(""));
	$(aEmailLink).html("&#121;&#111;&#103;&#105;&#104;&#105;&#107;&#101;&#115;&#064;&#103;&#109;&#097;&#105;&#108;&#046;&#099;&#111;&#109;");

};  // end UserPage.init()


/**
 * @description Display a larger image when clicking on an image in the index page.
 */

UserPage.prototype.imgCloseUp_click = function(e) {

	e.preventDefault();

	var img = $(e.target);	
	var smoke = $("#smoke");
	var imgCloseUp = $("#imgCloseUp");

	//
	// Get the dimensions of the window 
	//
	
	var docHeight = $(document).height();
	var winHeight = $(window).height();
	var docScrollTop = $(document).scrollTop();
	var width = $(window).width();
	var height = (docHeight > winHeight ? docHeight : winHeight);

	//
	// Set up the smoke styles
	//

	$(smoke).height(height);
	$(smoke).css("opacity", 0);	
	$(smoke).css("display", "block");	

	//
	// Closure to grow the dialog
	//
	
	var fGrowDialog = function() {
		var left = parseInt((width - 712) / 2);
		var topPos = parseInt(docScrollTop + 100);

		$(imgCloseUp).css("left", left + "px");
		$(imgCloseUp).css("top", topPos + "px");

		$(imgCloseUp).show("scale", {percent: 100}, 500, fLoadImage);
	}; 

	//
	// Closure to load the image
	//
	
	var fLoadImage = function() {
		var divCurvedContent = $(imgCloseUp).find("div.curvedContent");
		$(divCurvedContent).addClass("loading");

		var br = $(divCurvedContent).find("br");
		$(br).after('<img src="" alt="" style="display: none;" />');

		var imgCloseUpImg = $(divCurvedContent).find("img");

		$(imgCloseUpImg).load(
			function() {
				$(imgCloseUpImg).fadeIn("slow", function() { $(divCurvedContent).removeClass("loading"); });
			}
		);

		var src = $(img).attr("src").replace("height=230", "height=660");
		$(imgCloseUpImg).attr("src", src);
	};

	//
	// Display everything, starting with the smoke.
	// 
	
	$(smoke).animate({opacity: 0.2}, "fast", fGrowDialog);
		
}; // end UserPage.imgCloseUp_click()


/**
 * @description Close the imgCloseUp and fade out the smoke.
 */

UserPage.prototype.closeLink_click = function(e) {

	var imgCloseUp = $("#imgCloseUp");
	var smoke = $("#smoke");
	var divCurvedContent = $(imgCloseUp).find("div.curvedContent");
	var imgCloseUpImg = $(imgCloseUp).find("img");

	$(imgCloseUp).fadeOut(
		"normal",
		function() {
			$(divCurvedContent).removeClass("loading");
			$(imgCloseUpImg).remove();
			$(smoke).fadeOut("fast");
		}
	);	

}; // end UserPage.closeLink_click()


/**
 * @description Add to Cart method
 */

UserPage.prototype.addToCart_click = function(e) {

	e.preventDefault();

	var eAnchor = $(e.target);
	var productListId = null;
	var divProductDetails = $(eAnchor).closest("div.productDetails");
	var divProduct = $(eAnchor).closest("div.product");
	var spanProduct = $(eAnchor).closest("span.product"); // IE has span.product for use of display inline-block.

	if (divProductDetails && divProductDetails.length) { 	
		productListId = String(divProductDetails.attr("id")).split("-")[1];
		this.addToCartStatus[productListId] = $(divProductDetails).find("span.addToCartStatus");
	}
	else if (divProduct && divProduct.length) { 	
		productListId = String(divProduct.attr("id")).split("-")[1];
		this.addToCartStatus[productListId] = $(divProduct).find("span.addToCartStatus");
	}
	else if (spanProduct && spanProduct.length) { 	
		productListId = String(spanProduct.attr("id")).split("-")[1];
		this.addToCartStatus[productListId] = $(spanProduct).find("span.addToCartStatus");
	}

	this.addToCart(productListId);
};


/**
 * @description View Cart method
 */

UserPage.prototype.viewCart_click = function(e) {

	e.preventDefault();

	//
	// 1) Create the div#shoppingCartDetails table
	//

	var elTable = this.renderCart();
	this.shoppingCartDetails.html(elTable);


	//
	// 2) Remove collapse and add expand class on div#shoppingCart
	//

	this.shoppingCart.removeClass("collapse");
	this.shoppingCart.addClass("expand");

	//
	// 3) Grow the div#shoppingCartDetails and apply the onchange event for shipping
	//

	var that = this;

	this.shoppingCartDetails.slideDown(
		"slow", 
		function() {
			that.behavior(true);
		}
	);

}; // end UserPage.viewCart_click()


/**
 * @description Hide Cart method
 */

UserPage.prototype.hideCart_click = function(e) {

	if (e) { 
		e.preventDefault();
	}

	// Slide it up, then remove the details, and then toggle the 
	// expand/collapse classes on the shopping cart element.

	var that = this;	

	this.shoppingCartDetails.slideUp("slow", 
		function() {
			that.shoppingCart.removeClass("expand");
			that.shoppingCart.addClass("collapse");
		}
	);
};


/**
 * @description Update the cart total and shipping info upon selecting
 * a new shipping type (destinationId) 
 */

UserPage.prototype.selectShipping_change = function(e) {

	// 	
	// 1) Update destination id, calculate total, and get shipping cost.
	//

	this.destinationId = Number($(e.target).val());
	var total = this.calculateTotal();
	var shippingCost = this.calculateShipping(total);	

	//
	// 2) Update the HTML
	//

	var tdShippingCost = $(this.shoppingCartDetails).find("tr.shippingRow td.col3");
	var tdTotal = $(this.shoppingCartDetails).find("tr.totalRow td.col3");

	tdShippingCost.html("$" + shippingCost);
	tdTotal.html("Total: $" + (total + shippingCost));

	//
	// 3) Update the cart
	//

	this.updateCart();
	
}; // end UserPage.selectShipping_change()


/**
 * @description Update the cart with the changes made.
 */

UserPage.prototype.updateLink_click = function(e) {

	e.preventDefault();

	//
	// 1) Update the quantity in the cart
	//

	var parentTr = $(e.target).parents("tr");
	var rowId = Number((parentTr.attr("id").split("-"))[1]);
	var eQuantity = parentTr.find("input");
	var quantity = eQuantity.val();

	if (isNaN(quantity)) {
		eQuantity.val(this.cart[rowId].quantity);
		return;
	}
	else if (quantity == 0) {
		this.cart.splice(rowId, 1);
	}
	else {
		this.cart[rowId].quantity = Number(quantity);
	}

	//
	// 2) Update the shopping cart label
	//

	var total = this.calculateTotal("items");
	this.populateCartLabel(total);
	
	//
	// 3) Re-render the table and add it to the DOM
	//

	var elTable = this.renderCart();
	this.shoppingCartDetails.html(elTable);

	//
	// 4) Reapply behavior to the cart
	//

	this.behavior(true);

	//
	// 5) Update the cart on the server side
	//

	this.updateCart();

}; // end UserPage.updateLink_click()


/**
 * @description Remove an item from the cart.
 */

UserPage.prototype.removeLink_click = function(e) {

	e.preventDefault();
	
	//
	// 1) Remove the item from the cart
	//

	var parentTr = $(e.target).parents("tr");
	var rowId = Number((parentTr.attr("id").split("-"))[1]);
	this.cart.splice(rowId, 1);

	//
	// 2) Update the shopping cart label
	//

	var total = this.calculateTotal("items");
	this.populateCartLabel(total);

	//
	// 3) Re-render the table and add it to the DOM
	//

	var elTable = this.renderCart();
	this.shoppingCartDetails.html(elTable);

	//
	// 4) Reapply behavior to the cart
	//

	this.behavior(true);

	//
	// 5) Update the cart on the server side
	//

	this.updateCart();

}; // end UserPage.removeLink_click()


/**
 * @description Check out by generating PayPal URL.
 */

UserPage.prototype.checkOutLink_click = function(e) {

	e.preventDefault();

	//
	// Get total, shipping cost, and destination
	//

	var total = this.calculateTotal();
	var shipping = this.calculateShipping(total);
	var shippingType = "";

	if (this.destinationId == 1) {
		shippingType = "USA";
	}
	else if (this.destinationId == 2) {
		shippingType = "CAN";
	}
	else if (this.destinationId == 3) {
		shippingType = "INTL";
	}
	

	//
	// Create the PayPal URL
	//

	var url = [
		"https://www.paypal.com/cgi-bin/webscr?",
		"cmd=_cart&",
		"upload=1&",
		"business=yogihikes@gmail.com&",
		"return=http://www.pcthandbook.com&",
		"cancel_return=http://www.pcthandbook.com&",
		"currency_code=USD"
	];

	for (var i = 0; i < this.cart.length; i++) {
		var name = String(this.cart[i].name).replace(/\s/g, "_");
		// var amount = parseInt(this.cart[i].quantity) * parseInt(this.cart[i].price);
		var amount = this.cart[i].price;
		var quantity = this.cart[i].quantity;

		url.push("&");
		url.push("item_name_" + (i + 1) + "=" + name + "&");
		url.push("amount_" + (i + 1) + "=" + amount + "&");
		url.push("quantity_" + (i + 1) + "=" + quantity);
	}

	var last = this.cart.length + 1;

	url.push("&");
	url.push("item_name_" + last + "=" + shippingType + "_shipping&");
	url.push("amount_" + last + "=" + shipping + "&");
	url.push("quantity_" + last + "=1");

	url = url.join("");


	//
	// Close the cart
	//

	this.hideCart_click();


	//
	// Open PayPal page in new window
	//

	window.open(url);
	
}; // end UserPage.checkOutLink_click()



// -----------------------------------------------------------------------------
// AJAX Methods
// -----------------------------------------------------------------------------

/**
 * @description Make ajax request to add item to cart
 */

UserPage.prototype.addToCart = function(productListId) {
	var that = this;

	$.ajax({
		type: "POST",
		url: "buffer/addToCart.php", 
		data: {
			destinationId: this.destinationId,
			productListId: productListId
		},
		success: function(data, textStatus) { 
			that.addToCart_success(data, textStatus); 
		}, 
		error: function(XMLHttpRequest, textStatus, errorThrown) { 
			that.addToCart_error(XMLHttpRequest, textStatus, errorThrown); 
		},
		dataType: "json"
	});
};


UserPage.prototype.addToCart_success = function(data, textStatus) {
	if (data.status == "success") {

		//
		// Update the cart
		//

		this.cart = data.cart;
		var productListId = data.productListId;

		//
		// Update cart quantity
		//

		var total = 0;

		for (var i = 0; i < this.cart.length; i++) {
			total += this.cart[i].quantity;
		};

		this.populateCartLabel(total);

		//
		// Update Cart Status and make it go away in 5 seconds
		//

		this.addToCartStatus[productListId].html("Item added to cart");
		this.addToCartStatus[productListId].css("display", "block");
		this.addToCartStatus[productListId].css("visibility", "visible");

		var that = this;

		window.setTimeout(
			function() {
				$(that.addToCartStatus[productListId]).fadeOut(
					"normal", 
					function() {
						that.addToCartStatus[productListId].css("display", "block");
						that.addToCartStatus[productListId].css("visibility", "hidden");
						delete that.addToCartStatus[productListId];
					}
				)
			},
			2000
		);
	}
	else {
		this.parentProduct = null;
		this.addToCartStatus = null;
		this.addToCart_error();
	}
};


UserPage.prototype.addToCart_error = function(XMLHttpRequest, textStatus, errorThrown) {
	// TODO - Better error handling
	alert("Error adding item to cart!");
	return;
};


/**
 * @description Make ajax request to update cart
 */

UserPage.prototype.updateCart = function() {
	$.ajax({
		type: "POST",
		url: "buffer/updateCart.php", 
		data: {
			destinationId: this.destinationId,
			cart: $.toJSON(this.cart)
		},
		dataType: "json"
	});
};



// -----------------------------------------------------------------------------
// Rendering Methods
// -----------------------------------------------------------------------------

/*
 * @description Return the HTML for the Shopping Cart Details
 */

UserPage.prototype.renderCart = function() {

	// 
	// 1) Calculate the total and construct the table rows
	//

	var total = this.calculateTotal();

	var trElems = new Array();
	var tableClassName = '';

	if (this.cart && this.cart.length) { 
		for (var i = 0; i < this.cart.length; i++) {
			var className = '';
	
			if (i == this.cart.length - 1) {
				className = ' class="last"';
			}
	
			var tr = 
				'<tr' + className + ' id="item-' + i + '">' + 
					'<td class="col1"><input type="text" value="' + this.cart[i].quantity + '" /></td>' + 
					'<td class="col2 gray">' + this.cart[i].name + '</td>' +
					'<td class="col3 gray">$' + this.cart[i].price + '</td>' +
					'<td class="col4">' + 
						'<a href="javascript:void(0);" class="hoverLink updateLink">Update</a>' + 
						'<a href="javascript:void(0);" class="hoverLink removeLink">Remove</a>' + 
					'</td>' +
				'</tr>';
			
			trElems.push(tr);
		}
	}
	else {
		tableClassName = ' class="noItems"';
		trElems.push('<tr><td colspan="4">There are no items in your cart.</td></tr>');
	}

	//
	// 2) Calculate the shipping cost
	//

	var shippingCost = this.calculateShipping(total);

	//
	// 3) Construct the Shopping Cart Details HTML
	//

	var elTable = '<table' + tableClassName + '>' +
		'<thead>' +
			'<tr>' + 
				'<th class="col1">Qty</th>' +
				'<th class="col2">Item</th>' +
				'<th class="col3">Price</th>' +
				'<th class="col4">Action</th>' +
			'</tr>' + 
		'</thead>' +
		'<tfoot>' +
			'<tr class="shippingRow">' + 
				'<td class="col1">&nbsp;</td>' +
				'<td class="col2">Shipping: ' +
					'<select id="selectShipping">' + 
						'<option value="1"' + (this.destinationId == 1 ? ' selected="selected" ' : '') + '>USA</option>' + 
						'<option value="2"' + (this.destinationId == 2 ? ' selected="selected" ' : '') + '>CAN</option>' + 
						'<option value="3"' + (this.destinationId == 3 ? ' selected="selected" ' : '') + '>INTL</option>' + 
					'</select>' + 
				'</td>' + 
				'<td class="col3 gray">$' + shippingCost + '</td>' + 
				'<td class="col4">' + 
					'<a href="shipping.php" id="shippingInfoLink" class="hoverLink">Info</a>' + 
				'</td>' +
			'</tr>' + 
			'<tr class="totalRow">' + 
				'<td class="col1">&nbsp;</td>' +
				'<td class="col3" colspan="2">Total: <span class="gray">$' + (total  + shippingCost) + '</span></td>' +
				'<td class="col4">' + 
					'<a href="javascript:void(0);" id="checkOutLink" class="gray buttonLink">Check Out</a>' + 
				'</td>' +
			'</tr>' + 
		'</tfoot>' +
		'<tbody>' +
			trElems.join('') + 
		'</tbody>' +
	'</table>';

	return elTable;

}; // end UserPage.renderCart()


/**
 * @description Populate cart label
 */

UserPage.prototype.populateCartLabel = function(total) {
	this.shoppingCartLabel.html("Shopping Cart (" + total + (total == 0 || total > 1 ? " items)" : " item)"));
};



// -----------------------------------------------------------------------------
// Calculation Methods
// -----------------------------------------------------------------------------

/**
 * @description Calculate the total cost of the items in the cart
 */

UserPage.prototype.calculateTotal = function(type) {
	var total = 0;

	if (this.cart && this.cart.length) { 
		for (var i = 0; i < this.cart.length; i++) {
			if (type == "items") {
				total += parseInt(this.cart[i].quantity);
			}
			else { 
				total += parseFloat(this.cart[i].price * this.cart[i].quantity);
			}
		}
	}

	return total;
};


/**
 * @description Calculate the shipping cost based on the total cost
 * of items in the cart.
 */

UserPage.prototype.calculateShipping = function(total) {
	var shippingCost = 0;

	for (var i = 0; i < this.postage.length; i++) {
		if (Number(this.postage[i].destinationId) == this.destinationId) {
			if (Number(this.postage[i].totalGreaterThan) <= total && total <= Number(this.postage[i].totalLessThan)) {
				shippingCost = this.postage[i].price;
				break;
			}
		}
	}

	return Number(shippingCost);
};



// *****************************************************************************
// Global Instance
// *****************************************************************************

var oUserPage = new UserPage();

$(document).ready(function() {
	oUserPage.init();
});
