//**************************************************************//
//     Name: elcLayer.js
//     Use: creates a fexible sliding area that can scroll or
//              jump along either the x or y axis
//     Author: Anthony Sossong
//     Dependencies: elcLayer.js, elcImage.js
//    
//     Comments: 
//			8-May-06 : split initialize from constructor and
//			added reset method.
//
//**************************************************************//


//**************************************************************//
//                 COMPATABILITY VARIABLES
//**************************************************************//
var isMacIE = ((navigator.platform.indexOf("Mac") != -1) && (navigator.appVersion.indexOf('MSIE 5') != -1));


//**************************************************************//
//                     DEFAULTS & CONSTANTS
//**************************************************************//

SlideArea.DEFAULT_ANIM_DISTANCE = 2;
SlideArea.DEFAULT_ANIM_DELAY = 1;
SlideArea.DEFAULT_ANIM_TIMEOUT = 15000;
SlideArea.ANIMATE_JUMP = !(isMacIE);
SlideArea.DEFAULT_JUMP_UNITS = null;
SlideArea.DEFAULT_JUMP_ANIM_DISTANCE = 5;
SlideArea.DEFAULT_JUMP_ANIM_DELAY = 1;
SlideArea.DEFAULT_MAX_ARROW_PAIRS = 3;


//**************************************************************//
//                              CONSTRUCTOR
//**************************************************************//

function SlideArea(sObjName, sSlideId, sAxis, iClipLen, iUnitLen, sSlideTrackId, sSlideThumbId, sSlideTrackAxis) {
	this.animDist = SlideArea.DEFAULT_ANIM_DISTANCE;
	this.animDelay = SlideArea.DEFAULT_ANIM_DELAY;
	this.animTimeout = SlideArea.DEFAULT_ANIM_TIMEOUT;
	
	this.animateJump = (SlideArea.ANIMATE_JUMP);
	this.jumpUnits = SlideArea.DEFAULT_JUMP_UNITS;
	this.jumpAnimDist = SlideArea.DEFAULT_JUMP_ANIM_DISTANCE;
	this.jumpAnimDelay = SlideArea.DEFAULT_JUMP_ANIM_DELAY;
	
	this.maxArrowPairs = SlideArea.DEFAULT_MAX_ARROW_PAIRS;
	
	this.name = sObjName;
	
	this.animRepeater = null;
	this.animStartTime = null;
	this.animIncrement = null;
	this.animSettlePos = null;
	
	this.slideAxis = (sAxis && (sAxis == "x")) ? "x" : "y";

	this.clipLength = iClipLen;
	if (!this.clipLength || (this.clipLength < 1)) return this.fail("clipLength");
	
	this.slideLayer = new elcLayer(sSlideId);
	if (!this.slideLayer.obj) return this.fail("slideLayer");
	
	this.unitLength = (typeof(iUnitLen) != "undefined") ? iUnitLen : null;
	
	if ((typeof(sSlideTrackId) != "undefined") && (typeof(sSlideThumbId) != "undefined")) {
		this.slideTrack = new elcLayer(sSlideTrackId);
		if (!this.slideTrack.obj) return this.fail("slideTrack");
		
		this.slideTrack.thumb = new elcLayer(sSlideThumbId);
		if (!this.slideTrack.thumb.obj) return this.fail("slideTrack.thumb");
		this.slideTrack.thumb.obj.saObj = this;
		this.slideTrack.thumb.obj.onmousedown = SlideArea._handleOnMouseDown;
		this.slideTrack.axis = ((typeof(sSlideTrackAxis) != "undefined") && (sSlideTrackAxis == "x"))? "x" : this.slideAxis;
		this.lastCursorX = null;
		this.lastCursorY = null;
	} else {
		this.slideTrack = null;
	}
	
	this.minusArrowsArr = new Array();
	this.plusArrowsArr = new Array();
	
	this._initialize();
}


//**************************************************************//
//                       STATIC METHODS
//**************************************************************//

SlideArea._fixEvent = function(e) {
	if (typeof e == 'undefined') e = window.event;
	if (typeof e.layerX == 'undefined') e.layerX = e.offsetX;
	if (typeof e.layerY == 'undefined') e.layerY = e.offsetY;
	return e;
}

SlideArea._handleOnMouseDown = function(e) {
	e = SlideArea._fixEvent(e);
	var obj = this.saObj;
	
	obj.lastCursorX = e.clientX;
	obj.lastCursorY = e.clientY;
	
	document.saObj = obj;
	document.onmousemove = SlideArea._handleOnMouseDrag;
	document.onmouseup = SlideArea._handleOnMouseEnd;
	
	return false;
}

SlideArea._handleOnMouseDrag = function(e) {
	e = SlideArea._fixEvent(e);
	var obj = this.saObj;

	var ey = e.clientY;
	var ex = e.clientX;
	var x = parseInt(obj.slideTrack.thumb.x);
	var y = parseInt(obj.slideTrack.thumb.y);
	var nx = (obj.slideTrack.axis == "x") ? obj._fixNextThumbPos(x + (ex - obj.lastCursorX)) : x;
	var ny = (obj.slideTrack.axis == "y") ? obj._fixNextThumbPos(y + (ey - obj.lastCursorY)) : y;
	
	obj.slideTrack.thumb.moveTo(nx, ny);
	obj._moveTo(obj.slideLayerZero - (obj.slideLayerLength * (ny / obj.slideTrack.length)));
		
	obj._setSlideArrows(true);
	obj.lastCursorX = ex;
	obj.lastCursorY = ey;

	return false;
}

SlideArea._handleOnMouseEnd = function(e) {
	document.onmousemove = null;
	document.onmouseup = null;
	document.saObj = null;
}


//**************************************************************//
//                            PUBLIC METHODS
//**************************************************************//

SlideArea.prototype.jumpMinus = function(iDist) {
	var jumpDist = ((typeof(iDist) != "undefined") && (iDist > 0)) ? iDist : null;
	if (this._canSlideMinus()) {
		this._doJump(jumpDist, "minus");
	}
}

SlideArea.prototype.jumpPlus = function(iDist) {
	var jumpDist = ((typeof(iDist) != "undefined") && (iDist > 0)) ? iDist : null;
	if (this._canSlidePlus()) {
		this._doJump(-jumpDist, "plus");
	}
}

SlideArea.prototype.reset = function() {
	this._moveTo(this.slideLayerZero);
	this.slideLayer = new elcLayer(this.slideLayer.obj.id);
	this._initialize();
}

SlideArea.prototype.setSlideArrowOff = function() {
	this.slideArrowOver = null;
	this._setSlideArrows();
}

SlideArea.prototype.setSlideArrowOver = function(sImgObjName) {
	this.slideArrowOver = sImgObjName;
	this._setSlideArrows();
}

SlideArea.prototype.slideMinus = function() {
	if (this._canSlideMinus()) {
		this._userOverrideCurAction();
		this._doAnim("minus");
	}
}

SlideArea.prototype.slidePlus = function() {
	if (this._canSlidePlus()) {
		this._userOverrideCurAction();
		this._doAnim("plus");
	}
}

SlideArea.prototype.slideStop = function() {
	this._doStop();
	if (this.unitLength) {
		this._doSettleAnim();
	}
}


//**************************************************************//
//                          PRIVATE METHODS
//**************************************************************//

SlideArea.prototype._animAction = function(x,y) {
	if (!(this._checkStop())) {
		this.slideLayer.moveBy(x,y);
	}
	this._setSlideArrows();
}

SlideArea.prototype._canSlideMinus = function() {
	var curPos = this._getCurPos();
	return (curPos < this.animEndPoints[0]);
}

SlideArea.prototype._canSlidePlus = function() {
	var curPos = this._getCurPos();
	return (curPos > this.animEndPoints[this.animEndPoints.length - 1]);
}	

SlideArea.prototype._checkHasTimedOut = function() {
	var curTime = (new Date()).getTime();
	if (this.animStartTime && ((curTime - this.animStartTime) >= this.animTimeout)) {
		this._doStop();
		return true;
	}
	return false;
}

SlideArea.prototype._checkStop = function() {
	return ((this._checkWouldPassZero()) || (this._checkWouldPassEnd()) || (this._checkHasTimedOut()) || this._checkWouldPassSettlePos());
}

SlideArea.prototype._checkWouldPassEnd = function() {
	return this._checkWouldPassStop(this.animEndPoints[this.animEndPoints.length - 1]);
}

SlideArea.prototype._checkWouldPassSettlePos = function() {
	var wouldPassSettlePos = (this.animSettlePos && (this._checkWouldPassStop(this.animSettlePos)));
	this.animSettlePos = (wouldPassSettlePos) ? null : this.animSettlePos;
	return wouldPassSettlePos;
}

SlideArea.prototype._checkWouldPassStop = function(iFinalPos) {
	if (this._wouldPassMilestone(iFinalPos)) {
		this._doStop();
		this._moveTo(iFinalPos);
		return true;
	}		
	return false;
}

SlideArea.prototype._checkWouldPassZero = function() {
	return this._checkWouldPassStop(this.animEndPoints[0]);
}

SlideArea.prototype._doAnim = function(sDir) {
	var x = 0;
	var y = 0;
	this.animIncrement = (sDir == "minus") ? this.animDist : -this.animDist;
	if (this.slideAxis == "x") {
		x = this.animIncrement;
	} else if (this.slideAxis == "y") {
		y = this.animIncrement;
	}
	this._setRepeat(x,y);
}

SlideArea.prototype._doSettleAnim = function() {
	var settlePos = this._getClosestEndPointPos();
	this._slideTo(settlePos);
}

SlideArea.prototype._doStop = function() {
	this._endRepeat();
	this.slideArrowOver = null;
	this._setSlideArrows();
}

SlideArea.prototype._doJump = function(iDist, sDir) {
	this._userOverrideCurAction();
	if (iDist) {
		if (this.animateJump) {
			this._slideBy(iDist, true);
		} else {
			this._moveBy(iDist);
		}
	} else {
		if (this.unitLength) {
			this._doJumpByUnits(sDir);
		}
	}
}

SlideArea.prototype._doJumpByUnits = function(sDir) {
	var startPosIndx = this._getClosestEndPointIndx();
	var jumpUnits = (this.jumpUnits) ? this.jumpUnits : this.displayUnits;
	jumpUnits = (sDir == "minus") ? jumpUnits : -jumpUnits;
	var finalPosIndx = startPosIndx - jumpUnits;
	finalPosIndx = (finalPosIndx < 0) ? 0 : finalPosIndx;
	var maxPosIndx = this.slideLayerUnits - this.displayUnits;
	finalPosIndx = (finalPosIndx > maxPosIndx) ? maxPosIndx : finalPosIndx;
	if (this.animateJump) {
		this._slideTo(this.animEndPoints[finalPosIndx], true);
	} else {
		this._moveTo(this.animEndPoints[finalPosIndx]);
	}
	this._setSlideArrows();
}

SlideArea.prototype._endRepeat = function() {
	if (this.animRepeater) {
		window.clearInterval(this.animRepeater);
		this.animRepeater = null;
		this.animStartTime = null;
	}
}

SlideArea.prototype._fixNextThumbPos = function(iNextThumbPos) {
	var nextThumbPlusPos = iNextThumbPos + this.slideTrack.thumb.length;
	var isMinThumbPos = (iNextThumbPos < 0);
	var isMaxThumbPos = (nextThumbPlusPos > this.slideTrack.length);
	return (isMinThumbPos) ? 0 : ((isMaxThumbPos) ? (this.slideTrack.length - this.slideTrack.thumb.length) : iNextThumbPos);
}

SlideArea.prototype._getClosestEndPointIndx = function() {
	var curPos = this._getCurPos();
	var endPosIndx = 0;
	for (var i=0; i<this.animBreakPoints.length; i++) {
		if (curPos < this.animBreakPoints[i]) {
			endPosIndx = (i+1);
		}
	}
	return endPosIndx;
}

SlideArea.prototype._getClosestEndPointPos = function() {
	var endPointIndx = this._getClosestEndPointIndx();
	return this.animEndPoints[endPointIndx];
}

SlideArea.prototype._getCurPos = function() {
	var curPos = (this.slideAxis == "x") ? this.slideLayer.x : this.slideLayer.y;
	return (curPos) ? curPos : 0;
}

SlideArea.prototype._getCurThumbPos = function() {
	var curThumbPos;
	if (this.slideTrack) {
		var curThumbPos = (this.slideTrack.axis == "x") ? this.slideTrack.thumb.x : this.slideTrack.thumb.y;
	}
	return (curThumbPos) ? curThumbPos : 0;
}

SlideArea.prototype._initialize = function() {
	this.slideLayerZero = (this.slideAxis == "x") ? this.slideLayer.x : this.slideLayer.y;
	this.slideLayerZero = (this.slideLayerZero) ? this.slideLayerZero : 0;
	this.slideLayerLength = (this.slideAxis == "x") ? this.slideLayer.w : this.slideLayer.h;
	this.slideLayerEnd = (this.slideLayerZero - this.slideLayerLength + this.clipLength);
	
	if (this.unitLength && (this.unitLength > 0)) {
		this.slideLayerUnits = Math.floor(this.slideLayerLength / this.unitLength);
		this.displayUnits = Math.floor(this.clipLength / this.unitLength);
	} else {
		this.slideLayerUnits = null;
		this.displayUnits = null;
	}

	if (this.slideTrack) {
		this.slideTrack.length = (this.slideTrack.axis == "x") ? this.slideTrack.w : this.slideTrack.h;
		this.lastCursorX = null;
		this.lastCursorY = null;
	}
	
	this._initSlideTrack();
	this._setAnimEndPoints();
	this._setAnimBreakPoints();

	this._initSlideArrows();
	this.slideArrowOver = null;
	this._setSlideArrows();
}

SlideArea.prototype._initSlideArrowArr = function(sBaseName, sArrowArr) {
	for (var i=0; i<this.maxArrowPairs; i++) {
		var arrowImgObj = document.getElementById(sBaseName + i);
		if (arrowImgObj) {
			sArrowArr[sArrowArr.length] = new elcImage(arrowImgObj,null,true);
		} else {
			break;
		}
	}
}

SlideArea.prototype._initSlideArrows = function() {
	var minusArrowBaseName = this.name + ".minusArrow.";
	var plusArrowBaseName = this.name + ".plusArrow.";
	this._initSlideArrowArr(minusArrowBaseName,this.minusArrowsArr);
	this._initSlideArrowArr(plusArrowBaseName,this.plusArrowsArr);

}

SlideArea.prototype._initSlideTrack = function() {
	if (this.slideTrack) {
		this.slideTrack.scale = (this.clipLength / this.slideLayerLength);
		if (this.slideTrack.scale > 1) {
			this.slideTrack.scale = 1;
			this.slideTrack.thumb.hide();
		} else {
			this.slideTrack.thumb.length = Math.floor(this.slideTrack.length * this.slideTrack.scale);
			if (this.slideTrack.axis == 'x') {
				this.slideTrack.thumb.setWidth(this.slideTrack.thumb.length);
			} else {
				this.slideTrack.thumb.setHeight(this.slideTrack.thumb.length);
			}			
		}
	}
}

SlideArea.prototype._moveBy = function(iDist) {
	var x = 0;
	var y = 0;
	if (this.slideAxis == "x") {
		x = iDist;
	} else if (this.slideAxis == "y") {
		y = iDist;
	}
	this.slideLayer.moveBy(x,y);
}

SlideArea.prototype._moveTo = function(iFinalPos) {
	var x = (this.slideLayer.x) ? this.slideLayer.x : 0;
	var y = (this.slideLayer.y) ? this.slideLayer.y : 0;
	if (this.slideAxis == "x") {
		x = iFinalPos;
	} else if (this.slideAxis == "y") {
		y = iFinalPos;
	}
	this.slideLayer.moveTo(x,y);
}

SlideArea.prototype._setAnimBreakPoints = function() {
	this.animBreakPoints = new Array();
	if (this.unitLength) {
		for (var i=0; i<this.animEndPoints.length; i++) {
			var animBreakPoint = (this.animEndPoints[i] - (this.unitLength / 2));
			if (animBreakPoint > this.slideLayerEnd) {
				this.animBreakPoints[this.animBreakPoints.length] = animBreakPoint;
			} else {
				break;
			}
		}
	}
}

SlideArea.prototype._setAnimEndPoints = function() {
	this.animEndPoints = new Array();
	this.animEndPoints[this.animEndPoints.length] = this.slideLayerZero;
	if (this.slideLayerUnits) {
		for (var i=1; i<this.slideLayerUnits; i++) {
			var animEndPoint = (this.slideLayerZero - (i * this.unitLength));
			if (animEndPoint > this.slideLayerEnd) {
				this.animEndPoints[this.animEndPoints.length] = animEndPoint;
			} else {
				break;
			}
		}
	}
	this.animEndPoints[this.animEndPoints.length] = this.slideLayerEnd;
}

SlideArea.prototype._setRepeat = function(x, y) {
	this._endRepeat();
	this.animRepeater = window.setInterval(this.name + '._animAction(' + x + ',' + y + ')',this.animDelay);
	this.animStartTime = (new Date()).getTime();
}

SlideArea.prototype._setSlideArrows = function(bIgnoreTrack) {
	for (var i=0; i<this.minusArrowsArr.length; i++) {
		if (this._canSlideMinus()) {
			if (this.slideArrowOver && (this.minusArrowsArr[i].name == this.slideArrowOver)) {
				this.minusArrowsArr[i].setOver();
			} else {
				this.minusArrowsArr[i].setOn();
			}
		} else {
			this.minusArrowsArr[i].setOff();
		}
	}
	for (var i=0; i<this.plusArrowsArr.length; i++) {
		if (this._canSlidePlus()) {
			if (this.slideArrowOver && (this.plusArrowsArr[i].name == this.slideArrowOver)) {
				this.plusArrowsArr[i].setOver();
			} else {
				this.plusArrowsArr[i].setOn();
			}
		} else {
			this.plusArrowsArr[i].setOff();
		}
	}
	if (this.slideTrack && !bIgnoreTrack) {
		var nextThumbPos = this._fixNextThumbPos(Math.floor((this.slideLayerZero - this._getCurPos()) * this.slideTrack.scale));
		var x = (this.slideTrack.axis == "x") ? nextThumbPos : 0;
		var y = (this.slideTrack.axis == "y") ? nextThumbPos :  0;
		this.slideTrack.thumb.moveTo(x,y);
	}
}

SlideArea.prototype._slideBy = function(iDist) {
	var curPos = this._getCurPos();
	var finalPos = curPos + iDist;
	this._slideTo(finalPos);
}

SlideArea.prototype._slideTo = function(iFinalPos) {
	var curPos = this._getCurPos();
	this.animSettlePos = iFinalPos;
	var slideDir = (curPos < this.animSettlePos) ? "minus" : "plus";
	var canSlide = (((slideDir == "minus") && this._canSlideMinus()) || ((slideDir == "plus") && this._canSlidePlus()));
	if (canSlide && (this.animSettlePos != curPos)) {
		this._doAnim(slideDir);
	}
}

SlideArea.prototype._userOverrideCurAction = function() {
	this.animSettlePos = null;
	this._endRepeat();
}

SlideArea.prototype._wouldPassMilestone = function(iMilestone) {
	var curPos = this._getCurPos();
	var wouldPass = (this.animIncrement < 0) ? (curPos > iMilestone) : (curPos < iMilestone);
	var hasDistance = (Math.abs(this.animIncrement) >= Math.abs(iMilestone - curPos));
	return (wouldPass && hasDistance);
}


//**************************************************************//
//                           DEBUGGING CODE
//**************************************************************//
SlideArea.prototype.fail = function(sRequiredParam) {
	var msg = "The required param " + sRequiredParam + " is null or invalid.";
	//alert(msg);
	return this;
}