// utilities-photowall.js

function PhotoWall (aDocument, aColumnCount, aRowCount, aPhotoCount, aSquareCount, aBlendDuration, aUpdatePeriod) {
	
	// hijynx for using setInterval/setTimeout usage
	this.index = PhotoWall.instances.length;
	PhotoWall.instances[this.index] = this;
	
	// initialize the wall's http request and image preloader objects
	this.httpRequest = new HttpRequest(this);
	this.imagePreloader = new ImagePreloader(this);
	
	// initialize various properties using the provided arguments
	this.hostDocument = aDocument;
	this.columnCount = aColumnCount;
	this.rowCount = aRowCount;
	this.photoCount = aPhotoCount;
	this.squareCount = aSquareCount;
	this.blendDuration = aBlendDuration;
	this.updatePeriod = aUpdatePeriod;
	
	// initialize the wall's div data array
	this.divs = new Array();
	this.InitializeDivsArray();
	
	// initialize the wall's photos array
	this.photos = new Array();
	this.photosURL = "http://www.thiggins.com/assets/php/utilities-photowall-getphoto.php?i=";
	this.InitializePhotosArray();
	
	// initialize the wall's  squares array
	this.squares = new Array();
	this.squaresURL = "http://www.thiggins.com/assets/gif/2008.photowall-square.gif";
	this.InitializeSquaresArray();
	
	// initialize the wall's favorites array (asynchronous retrieval of data)
	this.favorites = new Array();
	this.favoritesMultiplier = 2.0;  // favorites length = favorites multiplier * photo count
	this.favoritesURL = "http://www.thiggins.com/assets/php/utilities-photowall-getfavorites.php?n=";
	this.InitializeFavoritesArray();
	
	// set an interval to initialize the wall
	this.updateInterval = setInterval("PhotoWall.instances[0].InitializeWall()", 40);
	
}
PhotoWall.instances = new Array();


PhotoWall.prototype.GetImageIndex = function (aURL) {
	var tIndex = -1;
	for (var i = 0; i < this.photos["images"].length; i++) {
		if (this.photos["images"][i]["url"] == aURL) { tIndex = i; }
	}
	return tIndex;
}


PhotoWall.prototype.HttpCallback = function (aString) {
	
	// convert the string into an array of favorite photo db ids (waiting for preload)
	// var tDBIDs = aString.split(",");
	var tFavoritesArray = aString.split("][");
	
	// initialize the preload images array
	var tPreloadImagesArray = new Array();
	
	// add the square image to the array
	var tSquareImage = new Array();
	tSquareImage["type"] = "square";
	tSquareImage["url"] = this.squaresURL;
	tPreloadImagesArray.push(tSquareImage);
	
	// add each image entry to the array
	for (var i = 0; i < tFavoritesArray.length; i++) {
		var tPhotoData = tFavoritesArray[i].split("|");
		var tPhotoImage = new Array();
		tPhotoImage["type"] = "photo";
		tPhotoImage["date"] = tPhotoData[0];
		tPhotoImage["description"] = tPhotoData[1];
		tPhotoImage["file"] = tPhotoData[2];
		tPhotoImage["gallery"] = tPhotoData[3];
		tPhotoImage["url"] = this.photosURL + tPhotoData[4];
		tPhotoImage["id"] = tPhotoData[4];
		tPhotoImage["copyright"] = tPhotoData[5];
		tPreloadImagesArray.push(tPhotoImage);
	}
	
	// preload the images
	this.imagePreloader.PreloadImages(tPreloadImagesArray);
	
}


PhotoWall.prototype.InitializeDivsArray = function () {
	
	// initialize the needed sub-arrays
	this.divs["elements"] = new Array();
	this.divs["available"] = new Array();
	this.divs["photo"] = new Array();
	this.divs["square"] = new Array();
	
	// walk each row and column of the photo wall
	for (var iRow = 1; iRow <= this.rowCount; iRow++) {
		for (var iCol = 1; iCol <= this.columnCount; iCol++) {
			
			// initialize a reference to the current div element
			var tElement = this.hostDocument.getElementById("photowall-image-" + iRow + "_" + iCol);
			
			// add the current div element to the all  sub-array
			this.divs["elements"].push(tElement);
			
			// add the current div element index to the available sub-array
			var tDivIndex = this.divs["elements"].length - 1;
			this.divs["available"].push(tDivIndex);
			
			// initialize the curent div element's display
			tElement.innerHTML = "&nbsp;";
			this.SetDivOpacity(tDivIndex, 0.0);
			
		}
	}
	
}


PhotoWall.prototype.InitializeFavoritesArray = function () {
	
	// use http request object to pull the favorites' indices arrays
	var tFavoritesURL = this.favoritesURL + (this.photoCount * this.favoritesMultiplier);
	this.httpRequest.GetURL(tFavoritesURL);
	
}


PhotoWall.prototype.InitializePhotosArray = function () {
	
	// initialize the needed sub-arrays
	this.photos["images"] = new Array();
	this.photos["available"] = new Array();
	this.photos["inuse"] = new Array();
	
}


PhotoWall.prototype.InitializeSquaresArray = function () {
	
	// initialize the needed sub-arrays
	this.squares["images"] = new Array();
	this.squares["available"] = new Array();
	this.squares["inuse"] = new Array();
	
}

PhotoWall.prototype.InitializeWall = function () {
	
	// declare some needed variables
	var tAvailable = 0;
	var tDivIndex = -1;
	var tGrabIndex = -1;
	var tNeeded = 0;
	
	// see what, if any images are needed and available, or if we're done initializing the wall
	if ((this.divs["square"].length < this.squareCount) && (this.squares["available"].length > 0)) {
		
		// determine the number of squares to draw
		tNeeded = this.squareCount - this.divs["square"].length;
		tAvailable = this.squares["available"].length;
		if (tAvailable < tNeeded) { tNeeded = tAvailable; }
		
		// draw the squares
		for (var i = 1; i <= tNeeded; i++) {
			
			// grab the first available square
			var tSquareIndex = this.squares["available"].splice(0, 1)[0];
			this.squares["inuse"].push(tSquareIndex);
			
			// pick a random available div element
			tGrabIndex = Math.floor(Math.random() * this.divs["available"].length);
			tDivIndex = this.divs["available"].splice(tGrabIndex, 1)[0];
			this.divs["square"].push(tDivIndex);
			
			// draw the square in the div
			this.divs["elements"][tDivIndex].innerHTML = "<img src=\"" + this.squares["images"][tSquareIndex]["url"] + "\" />";
			this.AnimateDivOpacity(tDivIndex, 100.0);
		
		}
		
	} else if ((this.divs["photo"].length < this.photoCount) && (this.photos["available"].length > 0)) {
		
		// determine the number of photos to draw
		var tNeeded = this.photoCount - this.divs["photo"].length;
		var tPhotosAvailable = this.photos["available"].length;
		if (tPhotosAvailable < tNeeded) { tNeeded = tPhotosAvailable; }
		
		// grab a random available photo
		tGrabIndex = Math.floor(Math.random() * this.photos["available"].length);
		tPhotoIndex = this.photos["available"].splice(tGrabIndex, 1)[0];
		this.photos["inuse"].push(tPhotoIndex);
			
		// pick a random available div element
		tGrabIndex = Math.floor(Math.random() * this.divs["available"].length);
		tDivIndex = this.divs["available"].splice(tGrabIndex, 1)[0];
		this.divs["photo"].push(tDivIndex);
			
		// draw the photo in the div
		var tTitle = this.StripTags(this.photos["images"][tPhotoIndex]["description"]) + " [" + this.photos["images"][tPhotoIndex]["id"] + "." + tPhotoIndex + "]";
		this.divs["elements"][tDivIndex].innerHTML = "<a href=\"" + this.photos["images"][tPhotoIndex]["file"] + "\" rel=\"lightbox[photowall]\" title=\"" + tTitle + "\"><img border=\"0\" src=\"" + this.photos["images"][tPhotoIndex]["url"] + "\" /></a>";
		this.AnimateDivOpacity(tDivIndex, 100.0);
		
	} else if ((this.divs["square"].length == this.squareCount) && (this.divs["photo"].length == this.photoCount)) {
		
		// clear the current update interval
		clearInterval(this.updateInterval);
		
		// set an interval to update the wall
		this.updateInterval = setInterval("PhotoWall.instances[0].UpdateWall()", this.updatePeriod);
		
	}

}

PhotoWall.prototype.PreloadCallback = function (aImage) {
	
	// check the image type
	if (aImage["type"] == "photo") {
		
		// add the image to the photos 'available' sub-array
		
		// add the image URL to the images sub-array
		this.photos["images"].push(aImage);
		
		// add the new index to the available sub-array
		var tNewIndex = this.photos["images"].length - 1;
		this.photos["available"].push(tNewIndex);
		
	} else if (aImage["type"] == "square") {
		
		// populate the squares sub-arrays
		for (var i = 1; i <= (this.squareCount + 1); i++) {
			
			// add the square URL to the images sub-array
			this.squares["images"].push(aImage);
			
			// add the new index to the available sub-array
			var tNewIndex = this.squares["images"].length - 1;
			this.squares["available"].push(tNewIndex);
			
		}
		
	}
	
}

PhotoWall.prototype.StripTags = function (aString) { return aString.replace(/<(?:.|\s)*?>/g, ""); }


PhotoWall.prototype.AnimateDivOpacity = function (aDivIndex, aTargetOpacity) {
	
	// set the opacity delta to apply
	var tOpacityDelta = (100.0 / this.blendDuration) * 50.0;
	
	// step the div's opacity towards its target
	var tNewOpacity = this.divs["elements"][aDivIndex].style.opacity * 100.0;
	if (tNewOpacity < aTargetOpacity) {
		tNewOpacity += tOpacityDelta;
		if (tNewOpacity > aTargetOpacity) { tNewOpacity = aTargetOpacity; }
	} else if (tNewOpacity > aTargetOpacity) {
		tNewOpacity -= tOpacityDelta;
		if (tNewOpacity < aTargetOpacity) { tNewOpacity = aTargetOpacity; }
	}
	this.SetDivOpacity(aDivIndex, tNewOpacity);
	if (tNewOpacity != aTargetOpacity) { 
		setTimeout("PhotoWall.instances[0].AnimateDivOpacity(" + aDivIndex + "," + aTargetOpacity + ")", 50); 
	}
	
}


PhotoWall.prototype.SetDivOpacity = function (aDivIndex, aOpacity) {
	
	// set the div tag's opacity (multi-browser compatibility)
	var tDiv = this.divs["elements"][aDivIndex];
	tDiv.style.opacity = (aOpacity / 100.0);
	tDiv.style.MozOpacity = (aOpacity / 100.0);
	tDiv.style.KhtmlOpacity = (aOpacity / 100.0);
	tDiv.style.filter = "alpha(opacity=" + aOpacity + ")";
	
}

PhotoWall.prototype.UpdateWall = function () {
	
	var tGrabIndex = -1;
	var tGrabRange = -1;
	var tAvailableDivIndex = -1;
	var tInuseDivIndex = -1;
	
	// pick a random in-use div element (photo or square)
	tGrabRange = this.divs["square"].length;
	if (this.photos["available"].length > 0) { tGrabRange += this.divs["photo"].length; }
	tGrabIndex = Math.floor(Math.random() * tGrabRange);
	if (tGrabIndex < this.divs["square"].length) {
		
		// get the in-use div element index
		tInuseDivIndex = this.divs["square"].splice(tGrabIndex, 1)[0];
		
		// get a new empty div element index
		tGrabIndex = Math.floor(Math.random() * this.divs["available"].length);
		tAvailableDivIndex = this.divs["available"].splice(tGrabIndex, 1)[0];
		
		// update the contents of the empty div
		this.divs["elements"][tAvailableDivIndex].innerHTML = "<img src=\"" + this.squares["images"][0]["url"] + "\" />";
		
		// update the sub-arrays
		this.divs["available"].push(tInuseDivIndex);
		this.divs["square"].push(tAvailableDivIndex);
		
		// animate both divs
		this.AnimateDivOpacity(tAvailableDivIndex, 100.0);
		this.AnimateDivOpacity(tInuseDivIndex, 0.0);
		
	} else {
		
		// adjust the grab index
		tGrabIndex -= this.divs["square"].length;
		
		// get the in-use div element index
		tInuseDivIndex = this.divs["photo"].splice(tGrabIndex, 1)[0];
		
		// get the in-use photo index
		var tInuseURL = this.divs["elements"][tInuseDivIndex].innerHTML.split("src=\"")[1];
		//tInuseURL = tInuseURL.substring(0, (tInuseURL.length - 2));
		tInuseURL = tInuseURL.substring(0, (tInuseURL.length - 6));
		tInuseURL = tInuseURL.split("\" border=")[0];
		var tInuseImageIndex = this.GetImageIndex(tInuseURL);
		if (tInuseImageIndex < 0) { alert(tInuseURL); }
		var tInuseArrayIndex = this.photos["inuse"].indexOf(tInuseImageIndex);
		var tTrash = this.photos["inuse"].splice(tInuseArrayIndex, 1)[0];
		
		// get a new empty div element index
		tGrabIndex = Math.floor(Math.random() * this.divs["available"].length);
		tAvailableDivIndex = this.divs["available"].splice(tGrabIndex, 1)[0];
		
		// get an available photo index
		tGrabIndex = Math.floor(Math.random() * this.photos["available"].length);
		var tAvailableImageIndex = this.photos["available"].splice(tGrabIndex, 1)[0];
		
		// update the contents of the empty div
		var tTitle = this.StripTags(this.photos["images"][tAvailableImageIndex]["description"]) + " [" + this.photos["images"][tAvailableImageIndex]["id"] + "." + tAvailableImageIndex + "]";
		this.divs["elements"][tAvailableDivIndex].innerHTML = "<a href=\"" + this.photos["images"][tAvailableImageIndex]["file"] + "\" rel=\"lightbox[photowall]\" title=\"" + tTitle + "\"><img border=\"0\" src=\"" + this.photos["images"][tAvailableImageIndex]["url"] + "\" /></a>";
		
		// update the sub-arrays
		this.divs["available"].push(tInuseDivIndex);
		this.divs["photo"].push(tAvailableDivIndex);
		this.photos["available"].push(tInuseImageIndex);
		this.photos["inuse"].push(tAvailableImageIndex);
		
		// animate both divs
		this.AnimateDivOpacity(tAvailableDivIndex, 100.0);
		this.AnimateDivOpacity(tInuseDivIndex, 0.0);
		
	}

}