/**
 * Class for the Accessory Details popup or print page.
 * Unlike the other page classes, this class is not instantiated when included,
 * since it is used from more places than just a single page (acc_v2_overview.jsp
 * and acc_v2_details_print.jsp). If used, the onLoad method of this class must
 * be invoked from the using class' onLoad method.
 */
var AccessoryDetails = Class.create();
AccessoryDetails.prototype = {
	standAlone: true,
	
	// Parameters for moving the popup DIV.
	smoothMoveDelta: 18,
	smoothMoveDelay: 10,

	// Constructor.
	initialize: function(baseTitle, standAlone) {
		this.baseTitle = baseTitle;
		this.standAlone = standAlone ? true : false;
		this.isPrintView = Util.getUrlParameters()["view"] == "print";
		this.showBackButton = Util.getUrlParameters()["showbackbutton"] == "true";
	},
	
	// Load-time setup.
	onLoad: function() {
		// Save original title.
		this.initialTitle = document.title;
		
		// Register details popup events.
		$("details_close_button_txt").onclick = this.onClose.bind(this);
		$("details_close_button_img").onclick = this.onClose.bind(this);
		
		// This link is only in details.jsp, so check its existence.
		var titlePrint = $("details_print_button_txt");
		if (titlePrint) {
			titlePrint.onclick = this.printDocument.bind(this);
		}
		
		// This link might be left out by details.jsp if not needed, so check its existence.
		this.addWishListLink = $("details_add_wishlist");
		if (this.addWishListLink) {
			this.addWishListLink.onclick = this.addToWishList.bind(this);
		}
		
		$("details_print_button").onclick = this.printerFriendlyVersion.bind(this);
		$("details_email_button").onclick = this.mailToFriend.bind(this);
		
		common.log("Details stand alone: " + this.standAlone);
		if (this.standAlone) {
			// Retrieve wish list for current user.
			common.beginBatch();
			common.retrieveWishList();

			var params = Util.getUrlParameters();
			var accessoryCode = params["accessoryCode"];
			if (accessoryCode != null) {
				this.showByPartCode(accessoryCode, "acc_details");
			}
			common.endBatch();
		} else {
			// Enable dragging of details.
			Event.observe("details_title", "mousedown", this.dragStart.bindAsEventListener(this));
		}
	},
	
	// Begin dragging details popup.
	dragStart: function(e) {
		if (this.details && !this.dragging) {
			this.dragging = true;
			this.details.style.cursor = 'move';
			this.lastDragX = Event.pointerX(e);
			this.lastDragY = Event.pointerY(e);
			
			this.dragMoveListener = this.dragMove.bindAsEventListener(this);
			Event.observe(document, "mousemove", this.dragMoveListener);
			
			this.dragEndListener = this.dragEnd.bindAsEventListener(this);
			Event.observe(document, "mouseup", this.dragEndListener);
		}
	},
	
	// Move details popup.
	dragMove: function(e) {
		var nextDragX = Event.pointerX(e);
		var nextDragY = Event.pointerY(e);
		var dx = nextDragX - this.lastDragX;
		var dy = nextDragY - this.lastDragY;
		this.lastDragX = nextDragX;
		this.lastDragY = nextDragY;
		Util.moveElement(this.details, dx, dy);
	},
	
	// End dragging details popup.
	dragEnd: function(e) {
		if (this.dragging) {
			Event.stopObserving(document, "mousemove", this.dragMoveListener);
			Event.stopObserving(document, "mouseup", this.dragEndListener);
			this.dragging = false;
			this.details.style.cursor = 'default';
		}
	},
	
	// Set the title to include the selected accessory name.
	setTitle: function(accessoryName) {
		document.title = accessoryName + " - " + this.baseTitle;
	},
	
	// Reset the title to original.
	clearTitle: function() {
		document.title = this.initialTitle;
	},
	
	// Retrieve the variation wish list cell for the given variation ID.
	getWishListCell: function(varPartCode) {
		return $("variationWishList-" + varPartCode);
	},
	
	// Fill the accessories DIV with the details of the given accessory.
	// The accessory is first loaded using the given ID.
	// If a DIV ID is given, the DIV is made visible. When the close button
	// is pressed and a closeCallback is given, that callback is invoked.
	showByPartCode: function(accessoryCode, detailsId, closeCallback, backOnCloseDetails) {
		this.accessoryCode = accessoryCode;
		this.showDetails(detailsId, closeCallback, backOnCloseDetails);

		// Retrieve the accessory details.		
		this.retrieveDetails(accessoryCode);
	},
	
	// Fill the accessories DIV with the details of the given accessory.
	// If a DIV ID is given, the DIV is made visible. When the close button
	// is pressed and a closeCallback is given, that callback is invoked.
	show: function(accessory, detailsId, closeCallback, backOnCloseDetails) {
		common.log("show: Accessory part code: " + accessory.partCode);
		this.accessoryCode = accessory.partCode;
		this.showDetails(detailsId, closeCallback, backOnCloseDetails);

		// If details have been loaded previously, we can display them directly.
		if (accessory.hasDetails) {
			this.updateDetails(accessory);
		} else {
			// Else retrieve them first.
			this.retrieveDetails(accessory.partCode);
		}
	},
	
	// Setup and show the details DIV if needed.
	showDetails: function(detailsId, closeCallback, backOnCloseDetails) {
		var params = Util.getUrlParameters();
		
		this.detailsId = detailsId;
		this.closeCallback = closeCallback;
		this.backOnCloseDetails = backOnCloseDetails;
		
		this.details = $(this.detailsId);
		if (this.details) {
			this.clearDetails();
			if (!Element.visible(this.detailsId)) {
				// Center popup over visible window size.
				Element.show(this.detailsId);
				this.centerDetails();
			}
			
			// Add close button if closeDetails parameter equals "exit".
			if (params["closeDetails"] == "exit") {
				if (this.closeCallback == null) {
					this.closeCallback = function() {};
				}
			}
			
			// Add print button if view parameter equals "print".
			if (params["view"] == "print") {
				Element.show("details_print_button_txt");
			}
			
			// Assume you only want to press escape if there is a close button.
			if (this.closeCallback) {
				if (this.onKeyDownListener == null) {
					this.onKeyDownListener = this.onKeyDown.bindAsEventListener(this);
					Event.observe(document, "keydown", this.onKeyDownListener);
				}
				this.details.focus();
			}
		}
		
		if (this.closeCallback == null) {
			Element.hide("details_close_button_txt");
			Element.hide("details_close_button_img");
		} else {
			Element.show("details_close_button_txt");
			Element.show("details_close_button_img");
		}
	},
	
	// Center the details DIV in the visible part of the screen.
	centerDetails: function(smoothMove) {
		var size = Util.getWindowSize();
		var offsets = Util.getScrollOffsets();
		var left = (size[0] - Math.floor(this.details.clientWidth - 10)) / 2 + offsets[0];
		var top = Math.max(20, Math.floor((size[1] - this.details.clientHeight) / 2)) + offsets[1];
		this.details.style.left = left + "px";
		
		if (!smoothMove) {
			this.details.style.top = top + "px";
		} else {
			var oldTop = parseInt(this.details.style.top);
			var delta = Math.abs(top - oldTop);
			if (delta < 5) {
				this.details.style.top = top + "px";
			} else {
				this.srcTop = oldTop;
				this.dstTop = top;
				var deltaMove = (oldTop < top) ? this.smoothMoveDelta : -this.smoothMoveDelta;
				this.setDetailsTop(deltaMove);
				this.moveTimer = window.setInterval(this.setDetailsTop.bind(this, deltaMove), this.smoothMoveDelay);
			}
		}
	},
	
	// Set the top of the details, and stop timer if we reached the destination.
	setDetailsTop: function(delta) {
		this.srcTop += delta;
		this.details.style.top = this.srcTop + "px";
		if (delta < 0 ? this.srcTop <= this.dstTop : this.dstTop <= this.srcTop) {
			window.clearInterval(this.moveTimer);
			this.moveTimer = null;
		}
	},
	
	// Hide the details DIV.
	hide: function() {
		if (this.details) {
			Element.hide(this.detailsId);
		}
	},
	
	// Invoked by the DIV key handler.
	onKeyDown: function(e) {
		common.log("Details.onKeyDown: " + e.keyCode);
		if (e.keyCode == 27 && Element.visible(this.detailsId)) { // Escape
			this.onClose();
		}
	},
	
	// Invoked by the close button.
	onClose: function() {
		this.dragEnd();
	
		if (this.onKeyDownListener != null) {
			Event.stopObserving(document, "keydown", this.onKeyDownListener);
			this.onKeyDownListener = null;
		}

		if (this.moveTimer != null) {
			window.clearInterval(this.moveTimer);
			this.moveTimer = null;
		}
		
		if (Util.getUrlParameters()["closeDetails"] == "exit") {
			window.close();
			return false;
		}

		if (this.closeCallback != null) {
			var done = this.closeCallback();
			if (done) {
				this.clearTitle();
				return false;
			}
		}
		
		this.clearTitle();
		this.hide();
		
		return false;
	},
	
	// Perform a DWR call to retrieve the details.
	retrieveDetails: function(accessoryCode) {
		this.accessoryDetails = null;
		AccessoryService.getAccessoryDetails(accessoryCode, 
			Config.countryCode, Config.languageCode, this.handleRetrieveDetails.bind(this));
	},
	
	// Handle the result from the DWR call to getAccessoryDetails() above.
	handleRetrieveDetails: function(accessory) {
		if (accessory == null) {
			this.onClose();
			return null;
		}
		
		this.accessoryDetails = accessory;
		this.updateDetails(accessory);
		
		// If no main image present, center directly.
		if ($("details-img-1") == null && !this.standAlone) {
			this.centerDetails();
		}
	},

	// Don't center until main image is ready, only then we know the total height of the popup.	
	onMainImageLoaded: function() {
		common.log("Main image loaded.");
		if (!this.standAlone) {
			this.centerDetails(true);
		}
		$("details-img-1").onload = null;
	},
	
	// Clear the details view.
	clearDetails: function() {
		$("details_title").innerHTML = "...";
		$("details_description").innerHTML = "";
		
		var images = $("details_images");
		while( images.childNodes.length > 0 ) {
			images.removeChild(images.firstChild);
		}
		
		Element.hide("details_variations_header");
		var variations = $("details_variations");
		while( variations.childNodes.length > 0 ) {
			variations.removeChild(variations.firstChild);
		}
	},
	
	// Update the view with the details of the accessory.
	updateDetails: function(accessory) {
		this.setTitle(accessory.displayName);
		$("details_title").innerHTML = accessory.displayName;
		
		var description = $("details_description");
		description.innerHTML = accessory.displayDescription || "";
				
		if (accessory.documentName != null && accessory.documentName.length > 0) {
			var shortName = accessory.documentName;
			var lastSlash = shortName.lastIndexOf("/");
			if (lastSlash != -1) {
				shortName = shortName.substring(lastSlash + 1);
			}
			
			with( DomBuilder ) {
				description.appendChild(
					fragment(
						p({className: "download"},
							span(text(Messages["common.download"])),
							br(),
							a({target: "_blank", href: common.getAccessoryDocument(accessory.documentName)},
								img({src: Config["downloadPDF.gif"], alt: ""})
							),
							a({target: "_blank", href: common.getAccessoryDocument(accessory.documentName)},
								text(shortName)
							),
							br()
						)
					)
				);
			}
		}
		
		var images = $("details_images");
		if (accessory.image1Name != null && accessory.image1Name.length > 0) {
			with( DomBuilder ) {
				images.appendChild(
					img({id: "details-img-1", imageName: accessory.image1Name, alt: "",
						 src: common.getAccessoryImage(accessory.image1Name),
						 onload: this.onMainImageLoaded.bind(this)}
					)
				)
			}
		}
		
		if (accessory.image2Name != null && accessory.image2Name.length > 0) {
			with( DomBuilder ) {
				images.appendChild(
					fragment(
						br(),
						div({className: "thumbnail"},
							text(Messages["details.thumbnailText"]),
							a({className: "thumbnail", href: "#", onclick: this.toggleImages.bind(this)},
								img({id: "details-img-2", imageName: accessory.image2Name, alt: "",
									 src: common.getAccessoryThumbnail(accessory.image2Name)})
							)
						)
					)
				)
			}
		}
		
		common.log("Details: vars: " + accessory.variations.length + ", local part code: " + accessory.localPartCode + ", yme part code: " + accessory.ymePartCode);
		if (this.addWishListLink) {
			Element.hide(this.addWishListLink);
		}

		if (accessory.variations.length > 0) {
			$("details_variations_header").innerHTML = accessory.variationDisplayHeading || "";
			Element.show("details_variations_header");
			
			var body = document.createElement("TBODY");
			
			for( var i = 0; i < accessory.variations.length; ++i ) {
				// Add a row for each variation.
				var v = accessory.variations[i];
				
				// Separator row.
				with( DomBuilder ) {
					body.appendChild(
						tr(td({colSpan: 4}, div({className: "lineHR"})))
					);
				}
				
				// Data row.
				with( DomBuilder ) {
					body.appendChild(
						tr(
							td({className: "description"}, text(v.description)),
							td({className: "partCode"}, text(v.partCode)),
							td({className: "price"},
								v.offerValid
									? fragment(
										span({className: "special"},
											text(
												Messages["common.currencySymbol"],
												formatFloat(v.offerPrice1,2), " ", 
												Messages["details.specialOffer"]
											)
										)
									)
									: (v.price1 > 0
										? text(Messages["common.currencySymbol"], formatFloat(v.price1,2))
										: text(" "))
							),
							this.isPrintView ? null : td({className: "wishlist", id: "variationWishList-" + v.partCodeEncoded},
								(common.isInClientWishList(v.partCode)
									? (common.enableRemoveFromWishList
										? a({className: "addWishList", href: "#", onclick: this.removeFromWishList.bind(this, v.partCode, v.partCode),
												title: Messages["common.removeWishList"]},
											img({src: Config["inWishList.gif"], alt: ""}),
											span({className: "wishlist"}, text(Messages["common.removeWishListShort"]))
										)
										: a({className: "addWishList", onclick: this.ignoreClickHandler},
											img({src: Config["inWishList.gif"], alt: ""}),
											span({className: "wishlist"}, text(Messages["common.inWishList"]))
										)
									)
									: a({className: "addWishList", href: "#", onclick: this.addToWishList.bind(this, v.partCode, v.partCode)},
										img({src: Config["addWishList.gif"], alt: ""}),
										span({className: "wishlist"}, text(Messages["common.addWishList"]))
									)
								)
							)
						)
					);
				}
			}
			
			var variations = $("details_variations");
			variations.appendChild(body);
		}
	},
	
	// Switch the hi-res and thumbnail image.
	toggleImages: function() {
		try {
			Element.setStyle(this.details, { cursor: "wait" });
				
			var img1 = $("details-img-1");
			var img2 = $("details-img-2");
			
			var otherImageName = img1.imageName;
			
			img1.imageName = img2.imageName;
			img1.src = common.getAccessoryImage(img2.imageName);
			
			img2.imageName = otherImageName;
			img2.src = common.getAccessoryThumbnail(otherImageName);
			
			return false;
		}
		
		finally {
			Element.setStyle(this.details, { cursor: "auto" });
		}
	},
	
	// Invoked by the "Print" button in the title bar.
	printDocument: function() {
		window.print();
		return false;
	},
	
	// Invoked by the "Printer friendly" button.
	printerFriendlyVersion: function() {
		var link = $("details_print_button").href;
		link += link.lastIndexOf("?") == -1 ? "?" : "&";
		link += "closeDetails=exit";
		link += "&accessoryCode=" + this.accessoryCode;
		
		// Signal to the AccessoryContext that JavaScript is enabled, and
		// that the accessory details need not be retrieved by the JSP.
		link += "&scriptingEnabled=true";
		
		Util.showPopup(link, "printDetails", {center: true, width: 730, height: 600, 
											  status: "no", menubar: "no",
											  resizable: "yes", scrollbars: "yes",
											  closeOnEscape: false});
		return false;
	},
	
	// Invoked by the "Mail to friend" button.
	mailToFriend: function() {
		var link = $("details_email_button").href;
		link += "?linkurl=" + encodeURIComponent(document.location.href) + "&linktext=" + encodeURIComponent(document.title);
		Util.showPopup(link, "mailToFriend", {center: true, width: 500, height: 600, closeOnEscape: false});
		return false;
	},
		
	// Invoked by the "Add to wish list" button to add the selected variation's part code
	// to the wish list.
	addToWishList: function(varPartCode) {
		if (!common.cookieCheck()) {
			return false;
		}
		
		var details = this.accessoryDetails;
		common.log("Details: adding to wish list: selected '" + varPartCode + "', acc: '" + details.partCode + "'");
		
		// Add this part code to the wish list.
		AccessoryService.addToWishList(varPartCode, Config.countryCode, Config.languageCode,
									   this.handleAddToWishList.bind(this, varPartCode));
		return false;
	},
	
	// Callback for DWR request AccessoryService.addToWishList() above.
	handleAddToWishList: function(varPartCode, added) {
		common.log("Part code '" + varPartCode + "': added: " + added);
		common.addToClientWishList(varPartCode);
		this.showAddWishList(varPartCode, false);
	},
	
	// Invoked by the "Remove from wish list" button with the part code of 
	// the clicked variation.
	removeFromWishList: function(varPartCode) {
		if (!common.cookieCheck()) {
			return false;
		}
		
		// Remove this part code from the wish list.
		AccessoryService.removeFromWishList(varPartCode, Config.countryCode, Config.languageCode,
									   this.handleRemoveFromWishList.bind(this, varPartCode));
		return false;
	},
	
	// Callback for DWR request AccessoryService.removeFromWishList() above.
	handleRemoveFromWishList: function(varPartCode, removed) {
		common.log("Part code '" + varPartCode + "': removed: " + removed);
		common.removeFromClientWishList(varPartCode);
		this.showAddWishList(varPartCode, true);
	},
	
	// Show "Add to wish list" or "In wish list" for the selected variation.
	showAddWishList: function(varPartCode, showAdd) {
		// Replace "Add to wish list" link.
		var cell = this.getWishListCell(varPartCode);
		if (cell != null) {
			// Find first link, that is the wish list button.
			var wishListLink = cell.getElementsByTagName("A")[0];
			
			if (showAdd) {
				wishListLink.onclick = this.addToWishList.bind(this, varPartCode);
				wishListLink.href = "#";
			} else {
				if (common.enableRemoveFromWishList) {
					wishListLink.onclick = this.removeFromWishList.bind(this, varPartCode);
					wishListLink.href = "#";
				} else {
					wishListLink.onclick = common.ignoreClickHandler;
					wishListLink.removeAttribute("href");
				}
			}
			
			var img = wishListLink.getElementsByTagName("IMG")[0];
			if (showAdd) {
				img.src = Config["addWishList.gif"];
			} else {
				img.src = Config["inWishList.gif"];
			}
			
			var span = wishListLink.getElementsByTagName("SPAN")[0];
			if (showAdd) {
				span.innerHTML = Messages["common.addWishList"];
				wishListLink.title = "";
			} else {
				if (common.enableRemoveFromWishList) {
					span.innerHTML = Messages["common.removeWishListShort"];
					wishListLink.title = Messages["common.removeWishList"];
				} else {
					span.innerHTML = Messages["common.inWishList"];
					wishListLink.title = "";
				}
			}
		}
	}
};

AccessoryDetails.checkStandAlone = function() {
	if (typeof AccessoryOverview == "undefined") {
		// Details is running stand-alone, create page class.
		// Create page class and initialize page when done loading.
		var page = new AccessoryDetails(Messages["details.title"], true);
		page.onLoad();
	}
};

Event.observe(window, "load", AccessoryDetails.checkStandAlone);
