//= require <mootools-core-1.3-full-nocompat>
//= require <uiframework/Panel>
//= require <uiframework/URLUtil>
//= require <findsalons/ListingSummary>
//= require <findsalons/PreviewPanel>
//= require <findsalons/Gallery>
//= require <findsalons/MyAccountViewMediator>
//= require <findsalons/MyAccountView>

var BottomCenterColumn = function()
{
	this.Extends = Panel;
	// Children
	this.pageTitle = null;
	this.overFlowPane = null;
	this.catImgWrapper = null;
	this.subCatsWrapper = null;
	this.summariesWrapper = null;
	this.previewPanel = null;
	this.listingDescription = null;
	this.gallery = null;
	this.myAccountView = null;
	// Properties
	this.currentPreview = null;
	this.content = null;
	this.contentChanged = false;
	this.updatePending = false;
	this.maxSubCatSize = 0;
	this.states = /^(home|category|listing|action)$/;
	// Child lists
	this.catImgs = null;
	this.listingSummaries = null;
	this.subCategories = null;
	this.freedSummaries = null;

	this.initialize = function()
	{
		this.parent("bottomCenterColumn");
		this.borderData(
		{
			topLeft : "img/top-left-lower-center-column.png",
			top : "img/lower-center-column-grad.png",
			topRight : "img/top-right-lower-center-column.png"
		});
		this.backgroundStyle(
		{
			"background-color" : "#FFF"
		});

		this.catImgs = [];
		this.subCategories = [];
		this.listingSummaries = [];
		this.freedSummaries = [];

		this.previewPanelFadeOutComplete = this.previewPanelFadeOutComplete.bind(this);
		this.previewPanel_mouseMoveHandler = this.previewPanel_mouseMoveHandler.bind(this);
	};

	this.commitProperties = function()
	{
		this.parent();
		if (this.contentChanged)
		{
			// Update only
			if (this.content.contentType == this.currentState)
				this.updatePending = true;
			else
				this.callLater(this.state.bind(this), [ this.content.contentType ]);

			this.contentChanged = false;
		}
		if (this.updatePending)
		{
			this.updateContent();
			this.updatePending = false;
		}
	};

	this.createChildren = function()
	{
		this.parent();

		this.previewPanel = new PreviewPanel('previewPanel');
		this.previewPanel.setActualSize(350, 200);

		if (!this.overFlowPane)
		{
			this.overFlowPane = new UIComponent('div',{
				"class":"overflowPane"
			});
			this.addChild(this.overFlowPane);
		}
	};

	this.updateDisplayList = function(width, height)
	{
		this.parent(width, height);
		switch (this.currentState)
		{
			case "home":
			case "category":
				this.layoutCategoryContent();
				break;

			case "listing":
				this.layoutListingContent();
				break;
				
			case "action":
				this.layoutActionContent();
				break;
		}
	};

	/**
	 * Sets the initial state of this control depending on the properties in the
	 * hash object or search string if present.
	 * 
	 * @param hash Object containing the key => value pairs that make up the hash.
	 */
	this.setInitializationState = function(hash /* Object */)
	{
		// Look for properties that we're interested in.
		var state = null;
		for ( var key in hash)
		{
			if (this.states.test(key))
			{
				state = key;
				break;
			}
		}
		if (location.search)
		{
			if (!state)
			{
				// We are using the DOM returned by the server.
				this.setStateBySearch();
				return;
			}
			else
			{
				// We have a hash and are expecting data
				this.killDOMState(URLUtil.searchStringToObject(location.search));
			}
		}
		else if (state)
		{
			// Defaults to kill to the home state
			this.killDOMState();
		}
		else
		{
			// No hash and no search string - default page state and DOM.
			this.state("home");
		}
	};

	this.setStateBySearch = function()
	{
		var hashObj = URLUtil.searchStringToObject(location.search);
		for ( var key in hashObj)
		{
			if (this.states.test(key))
			{
				this.state(key);
				return;
			}
		}
		this.state("home");
	};

	/**
	 * Removes elements that exist in the DOM in preparation for a state change.
	 * This method is called when both a hash and a search string exist on
	 * initialization.
	 * 
	 * @param hash
	 *            Object containing the key => value pairs that make up the hash
	 *            created from the search string.
	 */
	this.killDOMState = function(hash /* Object */)
	{
		// Kill the default state.
		this.killDefaultDOMState();
	};

	/**
	 * Removes DOM elements that may be present in the default state (category
	 * display) of the page. This method is called when both a search string and
	 * a hash are present.
	 */
	this.killDefaultDOMState = function()
	{
		var pageTitle = $("pageTitle");
		if (pageTitle)
			pageTitle.dispose();
		// -------------------------
		$$(".category-img").dispose();
		// ---------------------------
		$$(".category-post").dispose();
		//---------------------------
		$$(".gallery-images").dispose();
		//--------------------------
		$$(".post").dispose();
		// ---------------------------
		var summaries = $('listingSummaries');
		if (summaries)
			summaries.dispose();
		// ----------------------------
		var listingDescription = $("listing-description");
		if (listingDescription)
			listingDescription.dispose();
		//----------------------------
		var subCategories = $("subcategories");
		if (subCategories)
			subCategories.dispose();
	};

	/**
	 * @private Layout algo specific to category content.
	 */
	this.layoutCategoryContent = function()
	{
		var padding = 20;
		var verticalGap = 10;
		var horizontalGap = 10;
		var _w = this.width() - padding * 2;
		// ---------------------------------------------
		this.pageTitle.move(padding, padding);
		var posY = this.pageTitle._y + this.pageTitle.height() + verticalGap;
		// ---------------------------------------------
		var i = 0;
		var len = 0;
		if (this.catImgWrapper)
		{
			// Find the average image width
			// and the max image height
			var imageWidths = 0;
			var maxImageHeight = 0;
			len = this.catImgs.length;
			for (i = 0; i < len; i++)
			{
				var img = this.catImgs[i];
				imageWidths += img.width();
				maxImageHeight = Math.max(maxImageHeight, img.height());
			}
			// Size the wrapper to 125% of the max image height.
			this.catImgWrapper.setActualSize(_w, maxImageHeight * 1.25);
			this.catImgWrapper.move(padding, posY);

			// Distribute and center the images within the wrapper.
			var widthAllocation = _w / len;
			var imgAverage = imageWidths / len;
			var offset = (widthAllocation - imgAverage) / 2;
			for (i = 0; i < len; i++)
			{
				img = this.catImgs[i];
				img.move((widthAllocation * i) + offset, (this.catImgWrapper.height() - img.height()) / 2);
			}

			posY += this.catImgWrapper.height() + verticalGap;
		}
		// ------------------------------------------------
		if (this.overFlowPane)
		{
			this.overFlowPane.setActualSize(_w, Math.max(0, this.height() - posY));
			this.overFlowPane.move(padding, posY);
			posY = 0;
		}
		// -------------------------------------------------
		if (this.subCatsWrapper)
		{
			len = this.subCategories.length;
			var ms = this.maxSubCatSize + horizontalGap;
			var columns = (_w - (_w % ms)) / ms;
			var rows = Math.ceil(len / columns);
			var rowHeight = 22;
			// Test for an empty column
			if ((rows * columns) - len == rows)
				columns--;
			var rowCt = 0;
			var colCt = 0;
			var _allocation = _w / columns;
			var _offset = (_allocation - ms) / 2;
			for (i = 0; i < len; i++)
			{
				if (rowCt == rows)
				{
					rowCt = 0;
					colCt++;
				}
				var cat = this.subCategories[i];
				cat.move((_allocation * colCt) + _offset, (rowHeight * rowCt) + padding);
				rowCt++;
			}
			this.subCatsWrapper.setActualSize(_w, (rowHeight * rows) + (padding * 2));
			posY += this.subCatsWrapper.height() + verticalGap;
		}
		// --------------------------------------
		if (this.listingSummaries.length)
		{
			len = this.listingSummaries.length;
			var posX = 0;
			var localY = verticalGap;
			var localHeight = 0;
			for (i = 0; i < len; i++)
			{
				var listingSummary = this.listingSummaries[i];
				listingSummary.setActualSize((_w / 2) - horizontalGap, 75);
				listingSummary.move(posX, localY);
				if (i % 2 == 0)
				{
					posX = listingSummary.width() + horizontalGap;
					localHeight += listingSummary.height() + verticalGap;
				}
				else
				{
					posX = 0;
					localY += listingSummary.height() + verticalGap;
				}
			}
			this.summariesWrapper.setActualSize(_w, localHeight + verticalGap);
			this.summariesWrapper.move(0, posY);
		}
	};

	/**
	 * @private
	 * Lays out the listing content.
	 */
	this.layoutListingContent = function()
	{
		var padding = 20;
		var verticalGap = 10;
		var _w = this.width() - padding * 2;
		var posY = padding;
		// ---------------------------------------------
		this.pageTitle.move(padding, posY);
		posY += this.pageTitle.height();
		this.listingDescription.width(this.width() - (padding * 2));
		this.listingDescription.move(this.pageTitle._x, posY);
		posY += this.listingDescription.height() + verticalGap;

		if (this.overFlowPane)
		{
			this.overFlowPane.setActualSize(_w, Math.max(0, this.height() - posY));
			this.overFlowPane.move(padding, posY);
		}

		if (this.gallery)
		{
			var offset = 0;
			var ss = this.overFlowPane.getScrollSize();
			if (ss.y > this.overFlowPane.height())
				offset = 25;
			this.gallery.setActualSize(this.overFlowPane.width() - offset, 300);
		}
	};
	
	/**
	 * @private
	 * Lays out the action content.
	 */
	this.layoutActionContent = function()
	{
		var padding = 20;
		var _w = this.width() - padding * 2;
		var posY = padding;
		
		if (this.overFlowPane)
		{
			this.overFlowPane.setActualSize(_w, Math.max(0, this.height() - posY));
			this.overFlowPane.move(padding, posY);
		}
		if (this.myAccountView)
			this.myAccountView.setActualSize(_w, this.myAccountView.measuredHeight());
	};

	/**
	 * @inheritDoc
	 */
	this.commitNewState = function()
	{
		this.parent();
		if (this.states.test(this.newState))
			this.updatePending = true;
		else
			this.newStatePrevented = true;
	};

	this.updateContent = function()
	{
		this.cleanOldContent();
		switch (this.currentState)
		{
			case "home":
			case "category":
				this.showCategoryContent();
				break;

			case "listing":
				this.showListingContent();
				break;
				
			case "action":
				this.showActionContent();
				break;
		}
		this.invalidateDisplayList();
	};

	/**
	 * Shows the Category Content.
	 */
	this.showCategoryContent = function()
	{
		// ------------------------------------------------------------
		// page title
		var titleElement = $("pageTitle");
		if (titleElement)
			this.pageTitle = new UIComponent(titleElement);
		else
		{
			var categoryInfo = this.content['category']; // Object
			this.pageTitle = new UIComponent('h1',
			{
				id : "pageTitle",
				html : URLUtil.stripSlashes(categoryInfo.title)
			});
		}
		this.addChild(this.pageTitle);
		// ------------------------------------------------------------
		// Category images
		var catImgWrappers = $$(".category-img");
		if (catImgWrappers.length)
			this.createCatImagesFromElements(catImgWrappers);
		else
			this.createCatImagesFromJSON();
		// ------------------------------------------------------------
		// category posts
		var postElements = $$(".category-post");
		if (postElements && postElements.length)
			this.createPostsFromElements(postElements);
		else
			this.createPostsFromJSON();
		// ------------------------------------------------------------
		// sub-categories
		var subCatList = $('subcategories');
		if (subCatList)
			this.createSubCatsFromElement(subCatList);
		else
			this.createSubCatsFromJSON();
		// -------------------------------------------------------------
		// Listing Summaries
		var summaryData = $('listingSummaries');
		if (summaryData)
			this.createSummariesFromElement(summaryData);
		else
			this.createSummariesFromJSON();
	};

	this.showListingContent = function()
	{
		var titleElement = $("pageTitle");
		if (titleElement)
			this.pageTitle = new UIComponent(titleElement);
		else
		{
			this.pageTitle = new UIComponent("h1", {
				id:"pageTitle",
				html:URLUtil.stripSlashes(this.content.listing.title)
			});
		}
		this.addChild(this.pageTitle);
		//---------------------------
		var desc = $("listing-description");
		if (desc)
			this.listingDescription = new UIComponent(desc);
		else
		{
			this.listingDescription = new UIComponent("p", {
				id:"listing-description",
				html:URLUtil.stripSlashes(this.content.listing.description)
			});
		}
		this.addChild(this.listingDescription);
		//---------------------------
		// Look for a gallery
		var gallery = $$('.gallery-images');
		if (gallery && gallery.length)
			this.createGalleryFromElements(gallery[0]);
		else
			this.createGalleryFromJSON();
		var posts = $$(".post");
		if (posts && posts.length)
			this.createPostsFromElements(posts);
		else
			this.createPostsFromJSON();
	};
	
	this.showActionContent = function()
	{
		if (this.content.actionType == "myAccount")
		{
			if (!this.myAccountView)
			{
				this.myAccountView = new MyAccountView();
				this.dispatchEvent(new UICEvent("registerMediator", false, false, [MyAccountViewMediator, this.myAccountView]));
			}
			this.overFlowPane.addChild(this.myAccountView);
			this.myAccountView.dataProvider(this.content.listings);
		}
	};

	this.cleanOldContent = function()
	{
		while(this.overFlowPane.numChildren)
			this.overFlowPane.removeChild(this.overFlowPane.getChildAt(0));
		if (this.pageTitle)
		{
			this.removeChild(this.pageTitle);
			if (this.catImgWrapper)
				this.removeChild(this.catImgWrapper);
			if (this.listingDescription)
				this.removeChild(this.listingDescription);
			// --------------------------
			this.pageTitle = this.listingDescription = this.catImgWrapper = this.summariesWrapper = null;
			this.catImgs = [];
			if (this.subCategories.length)
			{
				this.subCategories.each(function(item)
				{
					item.parentComponent.removeChild(item);
				});
				this.subCategories = [];
				this.subCatsWrapper = null;
			}
			this.gallery = null;
		}
	};

	this.createCatImagesFromElements = function(wrappers /*Array of div Elements */)
	{
		var len = wrappers.length;
		if (len)
			this.createCatImgWrapper();
		for ( var i = 0; i < len; i++)
		{
			var wrapper = wrappers[i];
			var wrapperUIC = new UIComponent(wrapper);
			this.catImgWrapper.addChild(wrapperUIC);
			this.catImgs.push(wrapperUIC);
		}
	};

	this.createCatImagesFromJSON = function()
	{
		if (!this.content)
			return;
		var images = this.content['categoryImages'] || []; // Array of Objects
		var len = images.length;
		if (len)
			this.createCatImgWrapper();
		for ( var i = 0; i < len; i++)
		{
			var image = images[i]; // Object
			var href = image["href"];
			var wrapper = new UIComponent("div",
			{
				"class" : "category-img"
			});
			this.catImgWrapper.addChild(wrapper);
			wrapper.setActualSize(image.width.toInt(), image.height.toInt());
			var img = new UIComponent("img",
			{
				width : image.width,
				height : image.height,
				src : 'index.php?image=' + image.image_id,
				alt : URLUtil.stripSlashes(image.alt)
			});
			if (href)
			{
				var link = new UIComponent('a',
				{
					href : URLUtil.stripSlashes(href)
				});
				wrapper.addChild(link);
				link.addChild(img);
			}
			else
				wrapper.addChild(img);
			this.catImgs.push(wrapper);
		}
	};

	this.createPostsFromElements = function(posts /* Array of div Elements */)
	{
		var len = posts.length;
		for ( var i = 0; i < len; i++)
		{
			var post = posts[i];
			var postDiv = new UIComponent(post,
			{
				"styles" :
				{
					"position" : "relative"
				}
			});
			this.overFlowPane.addChild(postDiv);
		}
	};

	this.createGalleryFromElements = function(gallery /* ul Element */)
	{
		// Transform the ul into a dataProvider for the gallery.
		var items = gallery.getElements("ul");
		var len = items.length;
		if (len && !this.gallery)
		{
			this.gallery = new Gallery();
			this.overFlowPane.addChild(this.gallery);
		}
		var dp = [];
		for (var i = 0; i < len; i++)
		{
			var list = items[i];
			// Should have a thumbnail and the larger image
			var thumbnail = list.getElement('.gallery-thumb');
			var image = list.getElement('.gallery-image');
			dp.push({
				thumbnail:thumbnail,
				image:image
			});
			list.dispose();
		}
		if (this.gallery)
		{
			this.gallery.dataProvider(dp);
			gallery.dispose();
		}
	};

	this.createGalleryFromJSON = function()
	{
		if (!this.content)
			return;
		var galleryImages = this.content.galleryImages || []; // Array of objects
		var len = galleryImages.length;
		if (len && !this.gallery)
		{
			this.gallery = new Gallery();
			this.overFlowPane.addChild(this.gallery);
		}
		var dp = [];
		for (var i = 0; i < len; i++)
		{
			var image = galleryImages[i];
			dp.push({
				thumbnail:{
					width:image.thumb_width,
					height:image.thumb_height,
					alt:image.thumb_alt,
					src:"index.php?thumbnail="+image.thumb_id
				},
				image:{
					width:image.width,
					height:image.height,
					alt:image.alt,
					src:"index.php?image="+image.image_id
				}
			});
		}
		if (this.gallery)
			this.gallery.dataProvider(dp);
	};

	this.createPostsFromJSON = function()
	{
		if (!this.content)
			return;
		var posts = this.content.posts || []; // Array of Objects.
		var len = posts.length;
		for ( var i = 0; i < len; i++)
		{
			// Post contains a title <h1> and a body <p> but the object
			// also contains a creation_date and modification_date
			var post = posts[i];
			var postDiv = new UIComponent('div',
			{
				"class" : "category-post",
				"styles" :
				{
					"position" : "relative"
				}
			});
			this.overFlowPane.addChild(postDiv);
			if (post['title'])
			{
				var postTitle = new UIComponent('h1',
				{
					html : URLUtil.stripSlashes(post.title),
					"styles" :
					{
						"position" : "relative"
					}
				});
				postDiv.addChild(postTitle);
			}
			var postBody = new UIComponent('p',
			{
				html : URLUtil.stripSlashes(post.body),
				"styles" :
				{
					"position" : "relative"
				}
			});
			postDiv.addChild(postBody);
		}
	};

	this.createSubCatsFromElement = function(list /* Unordererd list Element */)
	{
		this.maxSubCatSize = 0;
		var data = list.dispose().getChildren('li');
		var len = data.length;
		if (len)
			this.createSubCatsWrapper();
		for ( var i = 0; i < len; i++)
		{
			var wrapper = new UIComponent('p',
			{
				html : data[i].get('html'),
				"class" : "subCategory"
			});
			this.subCatsWrapper.addChild(wrapper);

			this.maxSubCatSize = Math.max(this.maxSubCatSize, wrapper.width());
			this.subCategories.push(wrapper);
		}
	};

	this.createSubCatsFromJSON = function()
	{
		this.maxSubCatSize = 0;
		if (!this.content)
			return;
		var subCats = this.content['subCategories'] || [];
		var len = subCats.length;
		if (len)
			this.createSubCatsWrapper();
		for ( var i = 0; i < len; i++)
		{
			var subcat = subCats[i];
			var href = '<a href="index.php?category=' + subcat.category_id + '">' + URLUtil.stripSlashes(subcat.name) + '</a>' + ' (' + subcat.total_listings + ')';
			var wrapper = new UIComponent('p',
			{
				html : href,
				"class" : "subCategory"
			});
			this.subCatsWrapper.addChild(wrapper);

			this.maxSubCatSize = Math.max(this.maxSubCatSize, wrapper.width());
			this.subCategories.push(wrapper);
		}
	};

	this.createSummariesFromElement = function(element)
	{
		this.packSummaries();
		// we get a list of lists. Each containing a summary
		// Extract the summaries
		var summaries = element.getElements('.summary');
		var len = summaries.length;
		if (len)
			this.createSummariesWrapper();
		for ( var i = 0; i < len; i++)
		{
			// Create the dataProvider for each summary.
			// {logo:{image_id:<>, src:<>, width:<>, height:<>, alt:<>},
			// phone_number:<>, web_address:<>, title:<>}
			var dp = {};
			var summary = summaries[i];
			var logo = summary.getElement('.listingLogo');
			if (logo)
			{
				logo = logo.getElement('img').getProperties('src', 'width', 'height', 'alt');
				var idHash = URLUtil.searchStringToObject(logo.src);
				logo.image_id = idHash.image;
				dp.logo = logo;
			}
			var webAddress = summary.getElement('.listingWebsite');
			if (webAddress)
				dp.web_address = webAddress.getElement('a').get('html');

			var title = summary.getElement('.listingTitle');
			dp.title = title.getElement('a').get('html');
			dp.listing_id = URLUtil.searchStringToObject(title.getElement('a').get('href')).listing;
			dp.phone_number = summary.getElement('.listingPhone').get('html');

			this.createListingSummary(dp);
		}
	};

	this.createSummariesFromJSON = function()
	{
		this.packSummaries();
		if (!this.content)
			return;
		var summaryHash = this.content['listingSummaries'] || {};
		var summaries = summaryHash['data'] || [];
		var len = summaries.length;
		if (len)
			this.createSummariesWrapper();
		for ( var i = 0; i < len; i++)
		{
			// {logo:{image_id:<>, src:<>, width:<>, height:<>, alt:<>},
			// phone_number:<>, web_address:<>, title:<>}
			var summary = summaries[i];
			this.createListingSummary(summary);
		}
	};

	this.packSummaries = function()
	{
		var i = this.listingSummaries.length;
		while (i--)
		{
			var summary = this.listingSummaries[i];
			summary.mouseOutHandler();
			if (this.summariesWrapper)
				this.summariesWrapper.removeChild(summary);
			this.freedSummaries.push(summary);
		}
		this.listingSummaries = [];
	};

	this.createListingSummary = function(dp /* Object */)
	{
		var listingSummary = null;
		if (this.freedSummaries.length)
			listingSummary = this.freedSummaries.pop();
		else
			listingSummary = new ListingSummary();
		// ---------------------------------------
		listingSummary.dataProvider(dp);
		listingSummary.addEventListener("previewMouseOver", this.summary_previewMouseEnterHandler, false, 0, this);
		listingSummary.addEventListener("previewMouseOut", this.summary_previewMouseLeaveHandler, false, 0, this);
		this.summariesWrapper.addChild(listingSummary);
		this.listingSummaries.push(listingSummary);
	};

	this.createCatImgWrapper = function()
	{
		if (!this.catImgWrapper)
		{
			this.catImgWrapper = new UIComponent('div',
			{
				id : "categoryImages"
			});
			this.addChild(this.catImgWrapper);
		}
	};

	this.createSubCatsWrapper = function()
	{
		if (!this.subCatsWrapper)
		{
			this.subCatsWrapper = new UIComponent('div',
			{
				id : "subcategories"
			});
			this.overFlowPane.addChild(this.subCatsWrapper);
		}
	};

	this.createSummariesWrapper = function()
	{
		if (!this.summariesWrapper)
		{
			var id = this.subCatsWrapper ? "listingSummaries" : "listingSummaries1"; // See CSS
			this.summariesWrapper = new UIComponent('div',{
				id : id
			});
			this.overFlowPane.addChild(this.summariesWrapper);
		}
	};

	this.setContent = function(value /* Object */)
	{
		this.content = value;
		this.contentChanged = true;

		this.invalidateProperties();
	};
	// -------------------------------------------
	// Event Handlers

	this.summary_previewMouseEnterHandler = function(event /* UICEvent */)
	{
		if (this.currentPreview == event.target)
			return;
		this.previewPanel.get("tween").removeEvent("complete", this.previewPanelFadeOutComplete);
		this.currentPreview = event.target;
		application.addChild(this.previewPanel); // popup
		
		$(window).addEvent("mousemove", this.previewPanel_mouseMoveHandler);
		this.previewPanel.data(this.currentPreview.dataProvider());
		// ----------------------------------
		var mooEvent = event.data;
		this.previewPanel.move(mooEvent.client.x + 20, mooEvent.client.y - (this.previewPanel.height() / 2));
		this.previewPanel.addEventListener("updateComplete", this.previewPanel_updateComplete, false, 0, this);
		this.previewPanel.addEventListener("collectionChange", this.previewPanel_collectionChange, false, 0, this);
	};

	this.summary_previewMouseLeaveHandler = function(event /* UICEvent */)
	{
		this.currentPreview = null;
		this.previewPanel.get("tween").addEvent("complete", this.previewPanelFadeOutComplete);
		this.previewPanel.fade("out");
	};

	this.previewPanelFadeOutComplete = function()
	{
		application.removeChild(this.previewPanel);
		$(window).removeEvent("mousemove", this.previewPanel_mouseMoveHandler);
		this.previewPanel.removeEventListener("updateComplete", this.previewPanel_updateComplete);
	};

	this.previewPanel_mouseMoveHandler = function(event)
	{
		this.cx = event.client.x;
		this.cy = event.client.y;
		this.movePreviewPanel();
	};
	
	this.previewPanel_collectionChange = function()
	{
		this.previewPanel.fade("in");
	};
	
	this.previewPanel_updateComplete = function()
	{
		this.movePreviewPanel();
	};

	this.movePreviewPanel = function()
	{
		var rect = application.windowRect;
		var _w = this.previewPanel.width();
		var _h = this.previewPanel.height();
		var px = this.cx + 20;
		var py = this.cy - (_h / 2);
		if (px + _w > rect.x)
			px = this.cx - _w - 20;
		this.previewPanel.move(px, py);
		this.previewPanel.validateNow();
	}
};
BottomCenterColumn = new Class(new BottomCenterColumn());
