// Copyright (c) 2006. Adobe Systems Incorporated.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//   * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//   * Neither the name of Adobe Systems Incorporated nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

var Spry = new Object;

//////////////////////////////////////////////////////////////////////
//
// Spry.Utils
//
//////////////////////////////////////////////////////////////////////

Spry.Utils = new Object;

Spry.Utils.addClassName = function(ele, className) {
	if (!ele || !className || (ele.className && ele.className.search(new RegExp("\\b" + className + "\\b")) != -1)) {
		return;
	}
	ele.className += (ele.className ? " " : "") + className;
};

Spry.Utils.removeClassName = function(ele, className) {
	if (!ele || !className || (ele.className && ele.className.search(new RegExp("\\b" + className + "\\b")) == -1)) {
		return;
	}
	ele.className = ele.className.replace(new RegExp("\\s*\\b" + className + "\\b", "g"), "");
};

if (!Spry) Spry = {};
if (!Spry.Effects) Spry.Effects = {};

Spry.Effects.getElement = function(ele) {
	if (ele && typeof ele == "string") {
		return document.getElementById(ele);
	}
	return ele;
}

Spry.Effects.getStyleProp = function(element, prop) {
	try {
		if (element.style[prop]) {
			return element.style[prop];
		}
		else if (element.currentStyle) {
			return element.currentStyle[prop];
		}
		else if (document.defaultView && document.defaultView.getComputedStyle) {
			var style = document.defaultView.getComputedStyle(element, null);
			return style.getpropValue(prop);
		}
	}
	catch (e) {}
	return null;
};

Spry.Effects.Animator = function(options) {
	this.timer = null;
	this.interval = 0;
	this.stepCount = 0;
	this.options = {
		fps: 0,
		steps: 10,
		duration: 500,
		onComplete: null
	};
	this.setOptions(options);
	// If caller specified speed in terms of frames per second,
	// convert them into steps.
	if (this.options.fps > 0) {
		this.interval = Math.floor(1000 / this.options.fps);
		this.options.steps = parseInt((this.options.duration + (this.interval - 1)) / this.interval);
	}
	else if (this.options.steps > 0) {
		this.interval = this.options.duration / this.options.steps;
	}
	this.timeElapsed = 0;
};

Spry.Effects.Animator.prototype.setOptions = function(options) {
	if (!options) {
		return;
	}
	for (var prop in options) {
		this.options[prop] = options[prop];
	}
};

Spry.Effects.Animator.prototype.start = function() {
	var self = this;
	this.timer = setTimeout(function() { self.stepAnimation(); }, this.interval);
};

Spry.Effects.Animator.prototype.stop = function() {
	if (this.timer) {
		clearTimeout(this.timer);
	}
	this.timer = null;
};

Spry.Effects.Animator.prototype.stepAnimation = function() {
	++this.stepCount;
	this.animate();
	if (this.stepCount < this.options.steps) {
		this.start();
	}
	else if (this.options.onComplete) {
		this.options.onComplete();
	}
};

Spry.Effects.Animator.prototype.animate = function() {};

/////////////////////////////////////////////////////

Spry.Effects.Move = function(element, x, y, options) {
	Spry.Effects.Animator.call(this, options);
	this.element = Spry.Effects.getElement(element);
	this.stopX = x;
	this.stopY = y;
	this.x = Spry.Effects.getStyleProp(element, "left");
	this.y = Spry.Effects.getStyleProp(element, "top");
	if (!this.x || this.x == "auto") {
		this.x = element.offsetLeft;
	}
	else {
		this.x = parseInt(this.x);
	}
	if (!this.y || this.y == "auto") {
		this.y = element.offsetTop;
	}
	else {
		this.y = parseInt(this.y);
	}
	this.incrX = (this.stopX - this.x) / this.options.steps;
	this.incrY = (this.stopY - this.y) / this.options.steps;
	this.start();
};

Spry.Effects.Move.prototype = new Spry.Effects.Animator();
Spry.Effects.Move.prototype.constructor = Spry.Effects.Move;

Spry.Effects.Move.prototype.animate = function() {
	if (this.stepCount >= this.options.steps) {
		this.x = this.stopX;
		this.y = this.stopY;
	}
	else {
		this.x += this.incrX;
		this.y += this.incrY;
	}
	this.element.style.left = this.x + "px";
	this.element.style.top = this.y + "px";
};

/////////////////////////////////////////////////////

Spry.Effects.Size = function(element, w, h, options) {
	Spry.Effects.Animator.call(this, options);
	this.element = Spry.Effects.getElement(element);
	this.stopW = w;
	this.stopH = h;

	this.w = Spry.Effects.getStyleProp(element, "width");
	this.h = Spry.Effects.getStyleProp(element, "height");

	if (!this.w || this.w == "auto") {
		this.w = element.offsetWidth;
	}
	else {
		this.w = parseInt(this.w);
	}
	if (!this.h || this.h == "auto") {
		this.h = element.offsetHeight;
	}
	else {
		this.h = parseInt(this.h);
	}
	this.incrW = (this.stopW - this.w) / this.options.steps;
	this.incrH = (this.stopH - this.h) / this.options.steps;
	this.start();
};

Spry.Effects.Size.prototype = new Spry.Effects.Animator();
Spry.Effects.Size.prototype.constructor = Spry.Effects.Size;
Spry.Effects.Size.prototype.animate = function() {
	if (this.stepCount >= this.options.steps) {
		this.w = this.stopW;
		this.h = this.stopH;
	}
	else {
		this.w += this.incrW;
		this.h += this.incrH;
	}
	this.element.style.width = this.w + "px";
	this.element.style.height = this.h + "px";
};

/////////////////////////////////////////////////////

Spry.Effects.Opacity = function(element, opacity, options) {
	Spry.Effects.Animator.call(this, options);
	this.element = Spry.Effects.getElement(element);
	this.stopOpacity = opacity;
	this.opacity = Spry.Effects.getStyleProp(element, "opacity");
	if (!this.opacity) {
		this.opacity = 1.0; // Argh, just assume it is fully visible.
	}
	else {
		this.opacity = parseFloat(this.opacity);
	}
	this.incrO = (this.stopOpacity - this.opacity) / this.options.steps;
	this.start();
};

Spry.Effects.Opacity.prototype = new Spry.Effects.Animator();
Spry.Effects.Opacity.prototype.constructor = Spry.Effects.Opacity;
Spry.Effects.Opacity.prototype.animate = function() {
	if (this.stepCount >= this.options.steps) {
		this.opacity = this.stopOpacity;
	}
	else {
		this.opacity += this.incrO;
	}
	this.element.style.opacity = this.opacity;
	this.element.style.filter = "alpha(opacity=" + Math.floor(this.opacity * 100) + ")";
};

/////////////////////////////////////////////////////

// CSS Color Keywords:
Spry.Effects.cssColors = [];
Spry.Effects.cssColors["maroon"] = "#800000";
Spry.Effects.cssColors["red"] = "#ff0000";
Spry.Effects.cssColors["orange"] = "#ffA500";
Spry.Effects.cssColors["yellow"] = "#ffff00";
Spry.Effects.cssColors["olive"] = "#808000";
Spry.Effects.cssColors["purple"] = "#800080";
Spry.Effects.cssColors["fuchsia"] = "#ff00ff";
Spry.Effects.cssColors["white"] = "#ffffff";
Spry.Effects.cssColors["lime"] = "#00ff00";
Spry.Effects.cssColors["green"] = "#008000";
Spry.Effects.cssColors["navy"] = "#000080";
Spry.Effects.cssColors["blue"] = "#0000ff";
Spry.Effects.cssColors["aqua"] = "#00ffff";
Spry.Effects.cssColors["teal"] = "#008080";
Spry.Effects.cssColors["black"] = "#000000";
Spry.Effects.cssColors["silver"] = "#c0c0c0";
Spry.Effects.cssColors["gray"] = "#808080";

/////////////////////////////////////////////////////

Spry.Effects.SizeAndPosition = function(element, x, y, w, h, options) {
	this.mover = new Spry.Effects.Move(element, x, y, options);
	this.sizer = new Spry.Effects.Size(element, w, h, options);
};

Spry.Effects.SizeAndPosition.prototype.stop = function() {
	this.mover.stop();
	this.sizer.stop();
};

// Thumbnail stuff

// Global variables:
var gThumbWidth = 58;
var gThumbHeight = 58;
var gBehaviorsArray = [];

// Cancel the animation behavior of the object with the given id.
function CancelBehavior(id) {
  	if (gBehaviorsArray[id]) {
    	gBehaviorsArray[id].stop();
    	gBehaviorsArray[id] = null;
  	}
}

// Trigger the animation of the thumbnail growing.
function GrowThumbnail(img, width, height) {
  	Spry.Utils.addClassName(img, "inFocus");
  	img.style.zIndex = 99;
  	var id = img.getAttribute("id");
  	var twidth = Math.floor(width * .84);
  	var theight = Math.floor(height * .84);
  	var tx = (gThumbWidth - twidth) / 2;
  	var ty = (gThumbHeight - theight) / 2;
  	CancelBehavior(id);
  	gBehaviorsArray[id] = new Spry.Effects.SizeAndPosition(img, tx, ty, twidth, theight,{duration:400,steps:10,onComplete:function(b){gBehaviorsArray[id] = null;}});
}

// Trigger the animation of the thumbnail shrinking.
function ShrinkThumbnail(img) {
  	Spry.Utils.addClassName(img, "inFocus");
  	img.style.zIndex = 1;
  	var id = img.getAttribute("id");
  	CancelBehavior(id);
  	gBehaviorsArray[id] = new Spry.Effects.SizeAndPosition(img, 0, 0, gThumbWidth, gThumbHeight, {duration:400,steps:10,onComplete:function(b){gBehaviorsArray[id] = null; Spry.Utils.removeClassName(img, "inFocus");}});
}