LOVESceneController = new Class({

	initialize: function($director, version) {

		//console.log("LOVESceneController.initialize()");

		// TODO: abstract this into a separate class with constants?
		this.name = 'Wall';

		this.currentFilterTag;                      // contains last selected tag
		this.currentSearchString; 
		this.isHorizontallyScrolling = false;       // boolean indicating if the wall is sliding horizontally

		NUM_PAGE_BUTTONS = 5;                       // number of links to show in pagination

		THUMBNAIL_WIDTH = 205;
		THUMBNAIL_HEIGHT = 140;

		THUMB_SPACING = 30;                         // not padding, factored into final thumbnail height
		MARGIN_TOP_BOTTOM = 80;                     // ?

		DEFAULT_TAG = "lveDaily";                   // tag to load on initial load

		MIN_COLS = 1;
		MIN_ROWS = 1;
		MAX_COLS = 3;
		MAX_ROWS = 3;

		this.footer = $('footer');
		this.mainNav = $('mainNav');

		this.thumbContainerWidth;
		this.thumbContainerHeight;

		this.numCols = MIN_COLS;
		this.numRows = MIN_ROWS;

		this.panelfurthestExtent = 5;

		this.numThumbsPerPage = 0;

		this.isSearching = false;

		this.currentPageIndex;                      // current page index
		this.currentThumbStartIndex;                // absolute index of the first item on current page

		this.numPages = 0;                          // num pages
		this.numThumbs = 0;                         // total number of thumbs (per tag, not all)

		// TODO: set width to items from JS, not from CSS
		this.pageNumberWidth = 25;

		this.posts = new Array();

		// version control
		if (version == 'light') { }

		/**
		 *  All Morphs
 		 */

		this.paginationFX = new Fx.Morph($('footer-numbers-div').getElement('ul'), {
			duration: 1000,
			frameSkip: true,
			transition: Fx.Transitions.Quart.easeOut,
			link: 'cancel'
		});

		// Animate the entire wall
		// - Called when you come in and out of this page
		this.wallContentFX = new Fx.Morph("content-panel", {
			duration: (new LoveSettings()).PAGE_TRANSITION_DURATION,
			frameSkip: true,
			transition: (new LoveSettings()).PAGE_TRANSITION_TYPE,
			link: 'cancel'
		});

		// Animate the film strip within the Wall
		// - Invoked every time you load a new page
		this.wallAreaFX = new Fx.Morph('wall-area', {
			duration: 1000,
			link: 'cancel',
			transition: Fx.Transitions.Quart.easeOut,
			onComplete: function() {
				// Remove all thumbs that are out of range
				this.removeOutOfRangeThumbs();

				this.isHorizontallyScrolling = false;

			}.bind(this)
		});

		this.view = {
			wallarea : $('wall-area'),
			footer: $('footer-left'),
			footerright : $('footer-right'),
			versioning : $('mainNav-versioning'),
			hide : function(how, args) {
				var views = Scene_Wall.view;
				if (args == undefined) var args = [];
				for (v in views) {
					if (args.some(function(item, index) {
						return item == v;
					})) continue;
					if (typeOf(views[v]) != "function") views[v].view(how);
					if (typeOf(views[v]) == "function" && v != 'hide') {
						var els = views[v]().view(how);
					}
				}
			}
		};


		// add click event listeners
		$('footer-next').getElement('a').addEvent('click',
			function() {
				if (!this.isHorizontallyScrolling) {
					this.showNextPage();
				}
			}.bind(this)
		);

		$('footer-previous').getElement('a').addEvent('click',
			function() {
				if (!this.isHorizontallyScrolling) {
					this.showPreviousPage();
				}
			}.bind(this)
		);

		this.headerFX = new Fx.Morph(this.mainNav, {
			link: 'cancel',
			duration: 500
		});

		this.footerLeftFX = new Fx.Morph($('footer-left'), {
			link: 'cancel',
			duration: 500
		});

		this.footerRightFX = new Fx.Morph($('footer-right'), {
			link: 'cancel',
			duration: 500
		});

		// hide header and footers
		this.mainNav.view('hide');
		//this.mainNav.setStyle('opacity', 0.0);

 

		// update screen dimensions
		this.updateDimensions();
	},

	/**
	 *
	 */

	/**
	 * Called every time this controller is set to the forefront / is loaded
	 */

	PresentScene : function(fromScene) {

		//console.log("LOVEWallController.PresentScene()");
 
		/*
		// hide preloader
		spinner.hide();
		*/

		// update screen dimensions
		this.updateDimensions();

		// set width of pagination container
		$("footer-numbers-div").setStyles({"width": NUM_PAGE_BUTTONS * this.pageNumberWidth});

		// show header / footer
		this.showHeader();
		this.showFooter();

//		$('footer-left').view('in');

		// re-enable wall
		this.enableWall();

		// force a resize
		// TODO: consider using different criteria
		if (this.numPages > 0) {
			this.directorDidRequestResize();
		}

		// animate wall up (if not already in position)
		this.wallContentFX.start({
			'top': 0,
			'opacity': 1.0
		});
	},

	clearPosts: function(){
		// destroy all children of container
		var container = $$('.post-item-container');
		container.removeEvents();
		container.destroy();
	},

	/**
	 * This is called when the window has finished resizing (e.g: on mouse release / up)
	 */

	// TODO: this should probably fire on mouse release, not on a setTimeout
	// TODO: be awesome if this listened to dispatched events

	directorDidRequestResize: function() {

		// only execute if the wall is actually visible
		if ($('content-panel').isDisplayed()) {
 			
			var previousNumThumbsPerPage = this.numThumbsPerPage;

			// store the index of the first page before we reposition everything
			var storedThumbIndex = (this.currentPageIndex * this.numThumbsPerPage);

			// update dimensions
			this.updateDimensions();

			// update number of pages
			this.updateNumPages();

			// reposition thumbs and pagination if the number of max items per page has changed

			// check to see if wall is animating horizontally
			if (this.isHorizontallyScrolling) {
				// stop tween
				this.wallAreaFX.stop();
			}

			// Check to see if resizing has caused the grid has changed
			if (this.numThumbsPerPage != previousNumThumbsPerPage) {
 
				// re-create pagination
				this.rebuildBreadcrumbs();

				// Now we determine which page we will go to in order to see the first thumb on our previous layout
				// The total number of pages, as well as thumbs per page has changed.
				// Lets find out which page our stored index would sit on.
				var targetPageIndex = Math.floor(storedThumbIndex / this.numThumbsPerPage);

 
				// go to that page that has our target index on it
				this.showPageAt(targetPageIndex, false, true);
			} else {
				// snap wall into place
				this.repositionWall(false);

				// reposition thumbnails
				this.repositionThumbs();
			}
		}
	},

	/**
	 *
	 * @param version
	 */

	directorDidChangeVersionControl : function(version) {

	},

	/**
	 * Sets display none in the DOM and stops the wall from listening to resize events
	 */

	disableWall: function() {
		$('content-panel').view('hide');
	},

	/**
	 * Sets display: block in the DOM and allows the wall to listen to resize events
	 */

	enableWall: function() {
		$('content-panel').view('show');
	},

	/**
	 * Fetch wall thumbnails by search string.
	 * This is only done once
	 *
	 * @param searchString A string to filter all posts by
	 */

  	fetchPostsBySearchString: function(searchString) {
		//console.log(">>>\n");
		//console.log(">>> QUERY >>> LOVEWallController.fetchPostsBySearchString(): " + searchString);
		//console.log(">>>\n");

		this.currentSearchString = searchString;
		this.currentPageIndex = 0;
		this.isSearching = true;

		// reset wall position
		$('wall-area').setStyles({
			'left': 0
		});

		// show preloader
		spinner.show();

		var request = new Request.HTML({
			url:'pullSearchBatch.php',
			'async':true,
			'onSuccess':function(responseTree, responseElements, responseHTML, responseJavaScript) {
				//console.log(">>> QUERY >>> LOVEWallController.fetchPostsBySearchString(): success ");

				if(responseHTML == ""){
					Scene_Search.wallControllerDidChangeWall(0);
				} else {
					// determine total number of thumbs (with this tag)
					this.numThumbs = js_fetch_wall.elCount;

					// update number of pages based on how many thumbs we have
					this.updateNumPages();

					// re-create pagination
					this.rebuildBreadcrumbs();

					// show first page and animate into position
					this.showPageAt(0, true, true);

					Scene_Search.wallControllerDidChangeWall(this.numThumbs);
				}

			}.bind(this),

			'onFailure': function() {
				// TODO: manage error
			}.bind(this)

		}).get({
 			'fetchno': this.numThumbsPerPage,
			'searchString': searchString
		})  ;
	},
	
	/**
	 * Fetch wall thumbnails by post tag.
	 * This is only done once
	 * 
	 * @param bytag A string to filter all posts by
	 */

	fetchPostsByTag: function(bytag) {
		//console.log(">>>\n");
		//console.log(">>> QUERY >>> LOVEWallController.fetchPostsByTag(): " + bytag);
		//console.log(">>>\n");
		this.showFooter();
		this.currentFilterTag = bytag;
		this.currentPageIndex = 0;
		this.isSearching = false;

		// reset wall position
		$('wall-area').setStyles({
			'left': 0
		});

		// show preloader
		spinner.show();

		var request = new Request.HTML({
			url:'pullNextBatch.php',
			'async':false,
			onSuccess: function(responseTree, responseElements, responseHTML, responseJavaScript) {

				// hide preloader
				spinner.hide();

				// determine total number of thumbs (with this tag)
				this.numThumbs = js_fetch_wall.elCount;

				// update number of pages based on how many thumbs we have
				this.updateNumPages();

				// re-create pagination
				this.rebuildBreadcrumbs();

				// show first page and animate into position
				this.showPageAt(0, false, true);

			}.bind(this)
		}).get({
			's': 0,
			'fetchno': this.numThumbsPerPage,
			'typetag': this.currentFilterTag,
			'newtagrequest':'true'
		});
	},

	fetchThumbnailsByTag: function(previousPageIndex, startNumber, fetchCount, typetag, $animateWallBool, $thumbsChanged) {
		//console.log(">>>\n");
		//console.log(">>> QUERY >>> LOVEWallController.fetchThumbnailsByTag(): "+startNumber +", "+fetchCount+", "+typetag);
		//console.log(">>>\n");

		// TODO: revisit this
		this.currentThumbStartIndex = startNumber;

		// show preloader
		spinner.show();

		if ($thumbsChanged) {
			// destroy all children of container
			var container = $$('.post-item-container');
			container.removeEvents();
			container.destroy();
		}

		var newhtml = new Request.HTML({
			url:'pullNextBatch.php',
			'async':true,
			'onSuccess':function(responseTree, responseElements, responseHTML, responseJavaScript) {

				// hide preloader
				spinner.hide();

				// determine whether we're going forward or backward
				if ((previousPageIndex < this.currentPageIndex) ||
					(previousPageIndex == 0 && this.currentPageIndex == 0)) {
 					this.injectAfter(responseTree, startNumber, $thumbsChanged);
				} else {
 					this.injectBefore(responseTree, startNumber, $thumbsChanged);
				}

				// slide wall into place
				this.repositionWall($animateWallBool);

				// reposition thumbnails
				this.repositionThumbs();

			}.bind(this),

			'onFailure': function() {
				// TODO: manage error
			}.bind(this)
		}).get({
			's': startNumber,
			'fetchno':fetchCount,
			'typetag':this.currentFilterTag,
			'newtagrequest':'false'
		});
	},

	fetchThumbnailsBySearch: function(previousPageIndex, startNumber, fetchCount, searchString, $animateWallBool, $thumbsChanged) {
		//console.log(">>>\n");
		//console.log(">>> QUERY >>> LOVEWallController.fetchThumbnailsBySearch(): "+startNumber +", "+fetchCount+", "+searchString);
		//console.log(">>>\n");

		this.currentThumbStartIndex = startNumber;

		// show preloader
		spinner.show();

		if ($thumbsChanged) {
			// destroy all children of container
			var container = $$('.post-item-container');
			container.removeEvents();
			container.destroy();
		}

		var newhtml = new Request.HTML({
			url:'pullSearchBatch.php',
			'async':true,
			'onSuccess':function(responseTree, responseElements, responseHTML, responseJavaScript) {

				//console.log(">>> QUERY >>> LOVEWallController.fetchThumbnails(): success ");

				// hide preloader
				spinner.hide();

				// determine whether we're going forward or backward
				if ((previousPageIndex < this.currentPageIndex) ||
					(previousPageIndex == 0 && this.currentPageIndex == 0)) {
 					this.injectAfter(responseTree, startNumber, $thumbsChanged);
				} else {
 					this.injectBefore(responseTree, startNumber, $thumbsChanged);
				}

				// slide wall into place
				this.repositionWall($animateWallBool);

				// reposition thumbnails
				this.repositionThumbs();

			}.bind(this),

			'onFailure': function() {
				// TODO: manage error
			}.bind(this)
		}).get({
			's': startNumber,
			'fetchno': fetchCount,
			'searchString': searchString
		});
	},

	/**
	 * Returns an array of active thumbs / posts on the DOM
	 *
	 * @param $currentPage Boolean, set to true if you want to receive current items, set to false for everything else
	 */

	getActiveThumbs: function($currentPage) {
		//console.log("LOVEWallController.getActiveThumbs(): "+$currentPage);

		var startIndex = this.currentPageIndex * this.numThumbsPerPage;
		var endIndex = startIndex + this.numThumbsPerPage;

//		console.log("startIndex : "+startIndex);
//		console.log("endIndex : "+endIndex);

		var thumbs = new Array();

		var container = $$('.post-item-container');
		container.each(function(post, index) {

//			var postIndex = index + this.currentThumbStartIndex;
			var postIndex = post.customIndex;

			if (postIndex >= startIndex && postIndex < endIndex) {
			} else {
//				console.log("index: "+index + " is out of range ("+postIndex+")");
				thumbs.push(post);
			}
		}, this);

		return thumbs;
	},

	injectAfter: function($responseTree, $startNumber, $thumbsChanged) {
		// get total number of items
		var numItems = $responseTree.length;
		var countOffset = 0;
		// iterate through all items
		for (var i = 0; i < numItems; i++) {

			var post = $responseTree[countOffset];
			var postid = post.getAttribute('postid');

			var postExists = false;
			// check to see if it's been added
			for (var j=0; j<this.posts.length; j++) {
				if (postid == this.posts[j]) {
					postExists = true;
					break;
				}
			}

			if (postExists && !$thumbsChanged) {
//				console.log("post already loaded");
				post.setStyle('opacity', 1.0);
			} else {
//				console.log(i + ": post is new - add load event");
				// if it doesn't, set opacity to 0 and add a fade in load event

				// add image load events
				post.setStyle('opacity', 0.0);
				post.getElement("img").addEvent("load", function($post, $postid) {
					// fade in
					$post.set('morph', {
						duration: 1000,
						link: 'cancel'
					}).morph({
						opacity: [0, 1]
					});
				}.bind(this, post, postid));

				// push id into array to denote that it's been loaded
				Scene_Wall.posts.push(postid);
			}

			// check to see if post exists on the dom
			var postFound = false;
			$$('.post-item-container').each(function(post, index) {
				if (postid == post.getAttribute('postid')) {
//							alert('we got something');
					postFound = true;
				}
			});

			if (!postFound) {

				post.customIndex = $startNumber + i;

				// inject into DOM regardless
				post.inject($('wall-area'), 'bottom');
//				console.log("inject: "+post.customIndex);
			} else {
				countOffset+=1;
//				console.log("don't inject");
			}
		}
	},

	injectBefore: function($responseTree, $startNumber, $thumbsChanged) {

		// get total number of items
		var numItems = $responseTree.length - 1;
		var countOffset = $responseTree.length - 1;

		// iterate through all items
		for (var i = numItems; i >= 0; i--) {

//			console.log("countOffset: "+countOffset);

			var post = $responseTree[countOffset];
			var postid = post.getAttribute('postid');

			var postExists = false;
			// check to see if it's been added
			for (var j=0; j<this.posts.length; j++) {
				if (postid == this.posts[j]) {
					postExists = true;
					break;
				}
			}

			if (postExists && !$thumbsChanged) {
//				console.log("post exists");
				post.setStyle('opacity', 1.0);

			} else {
//				console.log("post DOESNT exist");

				// if it doesn't, set opacity to 0 and add a fade in load event

				// add image load events
				post.setStyle('opacity', 0.0);
				post.getElement("img").addEvent("load", function($post, $postid) {
					// fade in
					$post.set('morph', {
						duration: 1000,
						link: 'cancel'
					}).morph({
						opacity: [0, 1]
					});
				}.bind(this, post, postid));

				// push id into array to denote that it's been loaded
				Scene_Wall.posts.push(postid);
			}

			// check to see if post exists on the dom
			var postFound = false;
			$$('.post-item-container').each(function(post, index) {
				if (postid == post.getAttribute('postid')) {
//							alert('we got something');
					postFound = true;
				}
			});

			if (!postFound) {
				post.customIndex = $startNumber + i;

//				console.log("inject: "+post.customIndex);

				// inject into DOM regardless
				post.inject($('wall-area'), 'top');
				countOffset-=1;
			} else {
//				console.log("dont inject");
			}
		}
	},

	showFooter: function() {

		//console.log("LOVEWallController.showFooter()");

		$('footer-right').view('in');
 		$('footer-left').view('in');

	},

	hideFooter: function() {
//		console.log("LOVEWallController.hideFooter()");

		this.footerLeftFX.start({
			'opacity': 0.0
		}).chain(function() {
			$('footer-left').hide();
		}.bind(this));

		this.footerRightFX.start({
			'opacity': 0.0
		}).chain(function() {
			$('footer-right').hide();
		}.bind(this));
	},

	showHeader: function() {
//		console.log("LOVEWallController.showHeader()");

		this.mainNav.show();
		this.headerFX.start({
			'opacity': 1.0
		});
	},

	hideHeader: function() {
//		console.log("LOVEWallController.hideHeader()");

		this.headerFX.start({
			'opacity': 0.0
		}).chain(function() {
			this.mainNav.hide();
		}.bind(this));
	},

	showNextPage: function() {
 		if (this.currentPageIndex < this.numPages - 1) {
			this.showPageAt(this.currentPageIndex + 1, true, false);
		}
	},

	showPreviousPage: function() {
 		if (this.currentPageIndex > 0) {
			this.showPageAt(this.currentPageIndex - 1, true, false);
		}
	},

	/**
	 * Show page at $index
	 * 
	 * - retrieves thumbnails within a certain range
	 * - animates the wall based on $targetIndex
	 * - updates pagination to show selected section
	 *
	 * @param $index The index of the page we want to display
	 */

	showPageAt: function($index, $animateWallBool, $thumbsChanged) {
 
		// Determine the current and target page indices
		var previousPageIndex = this.currentPageIndex;

		// update page if the pageIndex has changed or if both previous and current page target indices are the same (e.g. on page 1)
//		if ($index != this.currentPageIndex || ($index == 0 &&  this.currentPageIndex == 0) )  {

			this.currentPageIndex = $index;

			// Use these indices to generate a post range to work with
			var startIndex, rangeLength;

//			console.log("this.currentPageIndex: "+ this.currentPageIndex);
//			console.log("previousPageIndex: "+previousPageIndex);

			if (this.currentPageIndex === previousPageIndex) {
//				console.log("same page");
				startIndex = this.currentPageIndex * this.numThumbsPerPage;
				rangeLength = this.numThumbsPerPage;
			} else {
				if (previousPageIndex <= this.currentPageIndex) {
//					console.log("going up");
					startIndex = (previousPageIndex + 1) * this.numThumbsPerPage;
					rangeLength = ((this.currentPageIndex - previousPageIndex)) * this.numThumbsPerPage;
				} else {
//					console.log("going down");
					startIndex = this.currentPageIndex * this.numThumbsPerPage;
					rangeLength = ((previousPageIndex - this.currentPageIndex)) * this.numThumbsPerPage;
				}
			}

			// fetch thumbnails either by search string or tag name
			if (this.isSearching) {
				this.fetchThumbnailsBySearch(previousPageIndex, startIndex, rangeLength, this.currentSearchString, $animateWallBool,$thumbsChanged);
			} else {
				this.fetchThumbnailsByTag(previousPageIndex, startIndex, rangeLength, this.currentFilterTag, $animateWallBool, $thumbsChanged);
			}
//		}

		// Underline currently selected item
		this.updatePagination();
	},

	/**
	 * Remove all thumbs on the DOM that aren't visible / out of range
	 */

	removeOutOfRangeThumbs: function() {
//		console.log("LOVEWallController.removeOutOfRangeThumbs");

		// get array of all active (visible) thumbs NOT on this page
		var thumbsOffPage = this.getActiveThumbs(false);

		// remove their events and destroy them
		thumbsOffPage.each(function(post, index) {
			thumbsOffPage[index].removeEvents();
			thumbsOffPage[index].destroy();
		});
		
	},
	
	updateDimensions: function() {
//		console.log("LOVEWallController.updateDimensions()");

		var w = THUMBNAIL_WIDTH + (2 * THUMB_SPACING);
		var h = THUMBNAIL_HEIGHT + (2 * THUMB_SPACING);

		// determine total number of cols and rows needed within our window
		this.numCols = Math.floor(window.getSize().x / w);
		this.numRows = Math.floor((window.getSize().y - MARGIN_TOP_BOTTOM) / h);

		// ensure that we have at least one row and four columns
		this.numCols = (this.numCols > MIN_COLS) ? this.numCols : MIN_COLS;
//		this.numCols = (this.numCols < MAX_COLS) ? this.numCols : MAX_COLS;

		this.numRows = (this.numRows > MIN_ROWS) ? this.numRows : MIN_ROWS;
		this.numRows = (this.numRows < MAX_ROWS) ? this.numRows : MAX_ROWS;

//		console.log("window width: "+window.getSize().x);
//		console.log("thumb width: "+w);

		// Determine total number of possible thumbs on this page
		this.numThumbsPerPage = (this.numRows * this.numCols);

		/*
		// TODO: look into this..
		this.numRows = Math.min(3, this.numRows);
		*/

//		this.thumbContainerWidth = Math.floor( (window.getSize().x) / this.numCols );
		this.thumbContainerWidth = (window.getSize().x) / this.numCols;
		this.thumbContainerHeight = h;
	},

	/**
	 * Underline currently selected line, fade in and out next and previous buttons
	 */

	updatePagination: function() {
 //		console.log(this.currentPageIndex);

		$$('#footer-right li').removeClass('footer-Active');

		// TODO: revisit this
// 		if (this.currentPageIndex) {
			if($$('#footer-right li')[this.currentPageIndex]) {
				$$('#footer-right li')[this.currentPageIndex].addClass('footer-Active');
			}
//		}

		// Show/hide previous and next buttons on first and last pages respectively
		if (this.currentPageIndex == 0) {
			$('footer-previous').fade('out');
		} else {
			// TODO: this shouldn't fade in from 0 if it's already at 100% opacity
			$('footer-previous').fade('in');
		}
		if (this.currentPageIndex == this.numPages - 1) {
			$('footer-next').fade('out');
		} else {
			// TODO: this shouldn't fade in from 0 if it's already at 100% opacity
			$('footer-next').fade('in');
		}

		/*
		// set width of pagination UL
		$("footer-numbers-div").getElement("ul").setStyles({
			'width': this.numPages * (this.pageNumberWidth * NUM_PAGE_BUTTONS)
		});

		console.log("total width: "+ (this.numPages * (this.pageNumberWidth * NUM_PAGE_BUTTONS)) );
		*/

		// set width of pagination inside container
		$("footer-numbers-div").getElement("ul").setStyles({"width": this.pageNumberWidth * this.numPages });

		// slide page numbers into place
		var pageNumberGroup = Math.floor(this.currentPageIndex / NUM_PAGE_BUTTONS);

		this.paginationFX.start({
			'left': -( pageNumberGroup * (this.pageNumberWidth * NUM_PAGE_BUTTONS) )
		});
	},

	rebuildBreadcrumbs : function() {
 
		// TODO: error check for totalelements == 0;

		// destroy all list elements and associated events
		for (var j=0; j<this.numThumbs; j++) {
			$$("#footer-numbers-div ul li").destroy();
			$$("#footer-numbers-div ul li").removeEvents();
		}

//		console.log("this.numPages: "+this.numPages);

		// create list elements
		for (var i=0; i<this.numPages; i++) {
			var li = new Element('li', {'class': 'page-number'}).appendText( i+1 );

			// add click event
			(function($this, $index){
				li.addEvent('click', function(event) {
					if (!$this.isHorizontallyScrolling) {
						$this.showPageAt($index, true, false);
					}
				});
			})(this, i);

			// inject into nav
			li.inject($("footer-numbers-div").getElement("ul"));
		}
	},

	// TODO: repositioning should really be done by CSS

	/**
	 *
	 * @param $animateBool Boolean whether the wall should tween into position or simply snap
	 */

	repositionWall: function($animateBool) {

		// Reposition / reanimate main wall
		if ($animateBool) {
			// slide to target page
			this.isHorizontallyScrolling = true;

			this.wallAreaFX.start({
				'left': -(window.getSize().x * this.currentPageIndex)
			});
		} else {
			// snap to target
			this.isHorizontallyScrolling = false;
			
			$('wall-area').setStyles({
				'left': -(window.getSize().x * this.currentPageIndex)
			});

			// Remove all thumbs that are out of range
			this.removeOutOfRangeThumbs();
		}
	},

	/**
	 * Called at launch and every time the window is resized
	 *
	 * Re-position EVERY thumb, even ones that are currently out of view frame
	 */

	repositionThumbs: function() {

//		console.log("LOVEWallController.repositionThumbs()");

		$$('.post-item-container').each(function(post, index) {

			// TODO: add load events for all thumbnails and have them fade in

			var postIndex = post.customIndex;

			/*
			post.setStyle('opacity', 0.0);
			post.getElement('img').addEvent("load", function() {
				post.morph({'opacity': 1.0});
			});
			*/

			// set custom property 'indexer', which is the absolute index of the thumbnail (out of all items)
			/*
			if (post.indexer == undefined) {
				post.indexer = ( index + this.currentThumbStartIndex );
			}
			*/

			/*
			var postIndex = index + this.currentThumbStartIndex;
			console.log("this.currentThumbStartIndex: "+this.currentThumbStartIndex);
			console.log("index: "+index);
			console.log("postIndex: "+postIndex);
			*/



			var relativeIndex = (index % this.numThumbsPerPage);

			// Determine (relative to the screen) col and row based on index
			var relativeColIndex = index % Math.floor(this.numThumbsPerPage / this.numRows);

			var absolutePageIndex = Math.floor(postIndex / this.numThumbsPerPage);

			var absoluteColIndex = relativeColIndex + (absolutePageIndex * this.numCols);
			var absoluteRowIndex = Math.floor(relativeIndex / this.numCols);

			// set new post width so that all posts fit snugly within the window
			var postPositionLeft = absoluteColIndex * this.thumbContainerWidth;
			var postPositionTop = absoluteRowIndex * this.thumbContainerHeight;

			// TODO: look into this
			var hh = ((window.getSize().y - this.thumbContainerHeight * this.numRows) / 2);

			// position .post-item-container
			post.setStyles({
				'top':  postPositionTop + hh,
				'left': postPositionLeft,
				'width': this.thumbContainerWidth,
				'height': this.thumbContainerHeight
			});


			post.wallXpos = postPositionLeft;
			post.wallYpos = postPositionTop + hh;
			// position .post-item-container > .post-item
			post.getElements('.post-item').setStyles({
				'width': this.thumbContainerWidth,
				'height': this.thumbContainerHeight
			});

			post.getElements('.post-item-img')[0].setStyles({
				'width':		THUMBNAIL_WIDTH,
				'height':	    THUMBNAIL_HEIGHT,
				'margin-top':   -(THUMBNAIL_HEIGHT * .5),
				'margin-left':  -(THUMBNAIL_WIDTH * .5)
			});

			post.getElements('.post-text-container')[0].setStyles({
				'width':		THUMBNAIL_WIDTH,
				'margin-left':  -(THUMBNAIL_WIDTH * .5),
				'height':		THUMBNAIL_HEIGHT
			});

			post.getElements('.post-text-frame')[0].setStyles({
				'width': THUMBNAIL_WIDTH
			});

		}, this);
	},

	explodeIn: function() {


			var evenCols = false,
			rows = this.numRows,
			columns = this.numCols,
			evenRows = false,
			centerCol1 =-1,
			centerCol2 =-1,
			l = 0,
			c = 0,
			distx = 2000,
			disty = 1000;

			if(columns %2 == 0) evenCols = true;
			if(rows %2 == 0) evenRows = true;
			if( evenCols ){ centerCol1 = Math.floor(columns/2); centerCol2 = Math.floor(columns/2)-1; }
			if( !evenCols ){ centerCol1 = Math.floor(columns/2); }


			var container = this.getActiveThumbs(true);
			container.each(function(items,index){
				items.set('morph',{'duration':4000});
				if(l == 1 && (c == centerCol1 || c == centerCol2) ) {
					var i = items; setTimeout(function(){ i.view('in'); }, 800 );
				}else{
					items.morph({'left':items.wallXpos, 'top': items.wallYpos});
				}

				if( (index+1) % (columns) == 0){
					l++; //new line
					c = 0; //start col
				}else{ c++; }

			});
	},

	explodeOut: function() {

  		var borderLength = (this.numCols * 2) + (this.numRows * 2) - 4;
 		var count = 0;
 		var container  =  $$('.post-item-container');
		var evenCols = false,
		rows = this.numRows,
		columns = this.numCols,
		evenRows = false,
		centerCol1 =-1,
		centerCol2 =-1,
		l = 0,
		c = 0,
		screenratio = window.getSize().x / 1000,
		distx = 1400 * screenratio,
		disty = 1400 * screenratio;

		if(columns %2 == 0) evenCols = true;
		if(rows %2 == 0) evenRows = true;
 		if( evenCols ){ centerCol1 = Math.floor(columns/2); centerCol2 = Math.floor(columns/2)-1; }
		if( !evenCols ){ centerCol1 = Math.floor(columns/2); }


		var highestleftside = { x : -distx, y :-disty };
		var lowestleftside = { x: window.getSize().x - distx, y :window.getSize().y + disty };

		highestrightside = { x : window.getSize().x + distx, y : window.getSize().y - disty  };
		lowestrightside = { x : window.getSize().x + distx, y : window.getSize().y + disty  };

		widthSegments = Math.abs(highestleftside.x - highestrightside.x) / columns;
		widthSegments += (widthSegments / columns);
		heightSegments = Math.abs(lowestleftside.y - highestleftside.y) / rows;
		heightSegments += (heightSegments / rows);

		container.each(function(items,index){
			
 			var xtarg = ((widthSegments * c) + highestleftside.x ) + ( window.getSize().x * Scene_Wall.currentPageIndex);
			var ytarg = (heightSegments * l) + highestleftside.y;
 			items.set('morph',{'duration':1500, transition: Fx.Transitions.Quad.easeOut});

		 	if(l == 1 && (c == centerCol1 || c == centerCol2) ) {
				items.view('hide');
			}else if(l==1 && rows==3){
				items.morph({'left':   xtarg, 'top': items.getStyle('top') });
 			}else{
				items.morph({'left':  xtarg, 'top': ytarg});
			}
  			if( (index+1) % (columns) == 0){
				l++; //new line
				c = 0; //start col
			}else{ c++; }

		});
	},

	updateNumPages: function() {
		// determine total number of required pages
		this.numPages = Math.ceil(this.numThumbs / this.numThumbsPerPage);

 	},

	updateNav: function($currentPage) {

		$$('#mainNav a').removeClass('selected');
		
		switch($currentPage) {
			case (LovePages.PAGE_BACKSTAGE):
				$('mainNav').getElementById('love_backstage').addClass('selected');
				break;
			case (LovePages.PAGE_DAILY):
				$('mainNav').getElementById('daily').addClass('selected');
				break;
			case (LovePages.PAGE_INSTANT):
				$('mainNav').getElementById('instant_love').addClass('selected');
				break;
			default:
				break;
		}
	},
	
	// TODO: pass in reference to this
	closeScene : function(forScene) {

		// hide footer
		this.hideFooter();

		switch (forScene.name) {
			case "Archive":

				// hide header
				this.hideHeader();

				// fade out wall
				this.wallContentFX.start({
					'opacity': 0.0
				}).chain(function() {
					// disable wall once it's out of view
					this.disableWall();
				}.bind(this));

				break;

			case "Feature":

				// hide header
				this.hideHeader();
  				this.explodeOut();
				// fade out wall
				this.wallContentFX.start({
					'opacity': 1.0
				}).chain(function() {
					// disable wall once it's out of view
					this.disableWall();
					var container = this.getActiveThumbs(true);
					container.each(function(items,index){ items.get('morph').cancel(); });
				}.bind(this));

				break;

			case "Search":

				// hide header
				this.hideHeader();

				break;

			case "Post":

				// hide header
				this.hideHeader();

				this.isHorizontallyScrolling = false;

				// slide up wall
				this.wallContentFX.start({
					'top': -window.getSize().y
				}).chain(function() {
					// disable wall once it's out of view
					this.disableWall();
				}.bind(this));

				break;

			case "Covers":

				// hide header
				this.hideHeader();

				this.isHorizontallyScrolling = false;

				// slide down wall
				this.wallContentFX.start({
					'top': window.getSize().y
				}).chain(function() {
					// disable wall once it's out of view
					this.disableWall();
				}.bind(this));

				break;
		}
	}
});
