var ie = document.all;

if (ie) { // An IE6 fix...
	try {
		document.execCommand("BackgroundImageCache", false, true);
	} catch(err) {}
}

var Rect = Class.create({
	initialize:function(x,y,w,h) {
		this.x = x;
		this.y = y;
		this.w = w;
		this.h = h;
	},
	inRect:function(x,y) {
		return ( // Are x and y in the bounds of this Rect?
			(x >= this.x) &&
			(x <= this.x + this.w) &&
			(y >= this.y) &&
			(y <= this.y + this.h)
		);
	},
	getRect:function() {
		return new Rect(this.x,this.y,this.w,this.h);
	}
});

var magRect = Class.create(Rect, {
	initialize:function($super,x,y,w,h) {
		$super(x,y,w,h);
	}
})

var linkRect = Class.create(Rect, {
	initialize:function($super,x,y,w,h,link) {
		this.link = link;
		$super(x,y,w,h);
	}
});

var popUpRect = Class.create(Rect, {
	initialize:function($super,x,y,w,h) {
		$super(x,y,w,h);
	}
});

var PageMap = Class.create(Enumerable, {  
	initialize: function() {
		var args = $A(arguments);
		if (!args.all(function(arg) {return arg instanceof Rect}))
			throw "PageMap must take an Rect as an argument."
		
		this.rects = args;
		
		this.reset();
	},
	setPos:function(x,y) {
		result = this.rects.find(function(rect) {
			if (rect.inRect(x,y))
				return true;
		});
		
		this.newArea = (result != this.lastResult);
		
		this.lastResult = result;
		
		
		if (result) {
			this.magArea = (result instanceof magRect);
			this.linkArea = (result instanceof linkRect);
			this.popUpArea = (result instanceof popUpRect)
			
			if (this.linkArea) {
				this.linkRect = result.getRect();
				this.link = result.link;
			}
				
			if (this.popUpArea)
				this.popUpRect = result.getRect();
		}
		else {
			this.reset();
		}
	},
	reset:function() {
		this.magArea = false;
		this.linkArea = false;
		this.popUpArea = false;
		
		this.lastResult = null;
	}
});
	
var Page = Class.create({
	initialize:function(imageFullSrc, imageScaledSrc, fullDim, scaledDim, magDim, map) {
		if (!imageFullSrc)
			throw "Must supply an argument for imageFullSrc";
		
		if (!imageScaledSrc)
			throw "Must supply an argument for imageScaledSrc";
			
		if (Object.isArray(fullDim) && Object.isNumber(fullDim.width) && Object.isNumber(fullDim.width))
			throw "Must supply an valid argument for 'fullDim'";
			
		if (Object.isArray(scaledDim) && Object.isNumber(scaledDim.width) && Object.isNumber(scaledDim.width))
			throw "Must supply an valid argument for 'scaledDim'";
			
		if (Object.isArray(magDim) && Object.isNumber(magDim.width) && Object.isNumber(magDim.width))
			throw "Must supply an valid argument for 'magDim'";
		
		if (!(map instanceof PageMap))
			throw "Must supply an valid PageMap argument for 'map'";
			
		this.imageFullSrc = imageFullSrc;
		this.imageScaledSrc = imageScaledSrc;
		this.fullDim = fullDim;
		this.scaledDim = scaledDim;
		this.magDim = magDim;
		this.map = map;
		
		this.imageRatio = {
			'x':fullDim.width/scaledDim.width,
			'y':fullDim.height/scaledDim.height
		};
		
		this.magRatio = {
			'x':(fullDim.width - magDim.width)/(scaledDim.width - magDim.width),
			'y':(fullDim.height - magDim.height)/(scaledDim.height - magDim.height)
		};
		
		this.bounds = {
			'left':Math.floor(this.magDim.width/2),
			'right':this.scaledDim.width - Math.floor(this.magDim.width/2),
			'width':this.scaledDim.width - this.magDim.width,
			'top':Math.floor(this.magDim.height/2),
			'bottom':this.scaledDim.height - Math.floor(this.magDim.height/2),
			'height':this.scaledDim.height - this.magDim.height
		};
	},
	build:function(parent) {
		if (!Object.isElement(parent))
			throw "Arugment 'parent' must be an element";
			
		this.imageScaled = new Element('img', {src:this.imageScaledSrc, alt:''}).setStyle({
			width:this.scaledDim.width+'px',
			height:this.scaledDim.height+'px'
		}).hide();
		
		//var imageFull = new Image();
		//imageFull.src = this.imageFullSrc;
		
		this.imageFull = new Element('div').setStyle({
			position:'absolute',
			border:'1px solid black',
			background:'url('+this.imageFullSrc+')',
			backgroundRepeat:'no-repeat'
		}).hide();
		
		$(parent).appendChild(this.imageScaled);
		$(parent).appendChild(this.imageFull);
		
		this.setOffset();
	},
	show:function() {
		this.imageScaled.show();
	},
	hide:function() {
		this.imageScaled.hide();
		this.imageFull.hide();
	},
	setOffset:function() {
		this.offset = {
			'left':this.imageScaled.cumulativeOffset().left,
			'top':this.imageScaled.cumulativeOffset().top
		};
	},
	startObservers:function() {
		if (Object.isUndefined(this.imageScaled) || Object.isUndefined(this.imageFull))
			throw "Must must build page first";
		
		$(document.body).observe('mousemove', this.mouseMove.bindAsEventListener(this));
		$(document.body).observe('click', this.mouseClick.bindAsEventListener(this));
	},
	stopObservers:function() {
		$(document.body).stopObserving('mousemove');
		$(document.body).stopObserving('click');
	},
	mouseMove:function(e) {
		// var startTime = getTime(); // for benchmarking
	
		var mouseScaledPos = new Object();
		var magPos = new Object();
		var mouseFullPos = new Object();

		
		mouseScaledPos.x = Event.pointerX(e) - this.offset.left;
		mouseScaledPos.y = Event.pointerY(e) - this.offset.top;
		
		if ((mouseScaledPos.x < 0) || (mouseScaledPos.x > this.scaledDim.width) || (mouseScaledPos.y < 0) || (mouseScaledPos.y > this.scaledDim.height)) {
			this.imageFull.hide();
			document.body.style.cursor='default';
			if (this.clickMessage) {
				this.clickMessage.remove();
				this.clickMessage = null;
			}
			this.map.reset();
		}
		else if (!this.map.popUpClicked) {
			this.map.setPos(mouseScaledPos.x, mouseScaledPos.y);
			
			if (this.map.magArea) {
				if (mouseScaledPos.x < this.bounds.left)
					magPos.x = 0;
				else if (mouseScaledPos.x > this.bounds.right)
					magPos.x = this.bounds.width;
				else
					magPos.x = mouseScaledPos.x - this.bounds.left;
					
				if (mouseScaledPos.y < this.bounds.top)
					magPos.y = 0;
				else if (mouseScaledPos.y > this.bounds.bottom)
					magPos.y = this.bounds.height;
				else
					magPos.y = mouseScaledPos.y - this.bounds.top;
						
				this.imageFull.setStyle({
					backgroundPosition:"-"+Math.floor(this.magRatio.x*magPos.x)+'px -'+Math.floor(this.magRatio.y*magPos.y)+'px',
					left:magPos.x+this.offset.left+'px',
					top:magPos.y+'px',
					width:this.magDim.width+'px',
					height:this.magDim.height+'px'
				}).show();
			}
			else {
				this.imageFull.hide();
			}
			
			if (this.map.linkArea || this.map.popUpArea) {
				if (this.map.newArea)
					document.body.style.cursor='pointer';
			}
			else {
				document.body.style.cursor='default';
			}
				
			if (this.map.linkArea) {
				if (this.map.newArea) {
					if (this.clickMessage) {
						this.clickMessage.remove();
						this.clickMessage = null;
					}
				
					document.body.appendChild(
						this.clickMessage = new Element('div').setStyle({
							position:'absolute',
							width:'auto',
							height:'auto',
							textAlign:'center',
							background:'#FFFFCC',
							color:'#339900',
							border:'1px solid black',
							zIndex:100
						}).hide().insert("Click to View This on FreshAcresMarket.com")
					)
					
					this.clickMessage.setStyle({
						left:this.offset.left+this.map.linkRect.x+Math.floor((this.map.linkRect.w - this.clickMessage.getWidth())/ 2)+'px',
						top:this.offset.top+this.map.linkRect.y+Math.floor((this.map.linkRect.h - this.clickMessage.getHeight())/ 2)+'px'
					}).show();
				}
			}
			else if (this.map.popUpArea) {
				if (this.map.newArea) {
					if (this.clickMessage) {
						this.clickMessage.remove();
						this.clickMessage = null;
					}
				
					document.body.appendChild(
						this.clickMessage = new Element('div').setStyle({
							position:'absolute',
							width:'auto',
							height:'auto',
							textAlign:'center',
							background:'#FFFFCC',
							color:'#339900',
							border:'1px solid black',
							zIndex:100
						}).hide().insert("Click to Zoom")
					)
					
					this.clickMessage.setStyle({
						left:this.offset.left+this.map.popUpRect.x+Math.floor((this.map.popUpRect.w - this.clickMessage.getWidth())/ 2)+'px',
						top:this.offset.top+this.map.popUpRect.y+Math.floor((this.map.popUpRect.h - this.clickMessage.getHeight())/ 2)+'px'
					}).show();
				}
			}
			else {
				if (this.clickMessage) {
					this.clickMessage.remove();
					this.clickMessage = null;
				}
			}
		}
			
		//debug(getTime() - startTime);
	},
	mouseClick:function(e) {
		if (this.map.linkArea) {
			window.location=this.map.link;
		}
		else if (this.map.popUpArea && !this.map.popUpClicked) {
			this.map.popUpClicked = true;
			
			var viewportDim = document.viewport.getDimensions();
			var scrollOffsets = document.viewport.getScrollOffsets();
			var popUpImageDim = new Object;

			document.body.appendChild(
				this.overlay = new Element('div').setStyle({
					position:'absolute',
					width:viewportDim.width+'px',
					height:viewportDim.height+'px',
					left:scrollOffsets.left+'px',
					top:scrollOffsets.top+'px',
					background:'#000000',
					zIndex:100
				}).hide()
			);
			
			
			new Effect.Appear(this.overlay, { duration: 0.2, from: 0.0, to: 0.8 });
			
			var rect = this.map.popUpRect.getRect();
			
			popUpImageDim.width = Math.floor(rect.w * this.imageRatio.x);
			popUpImageDim.height = Math.floor(rect.h * this.imageRatio.y);
			
			var clonedImageFull = this.imageFull.cloneNode(true);
					
			document.body.appendChild(
				this.popUp = new Element('div').setStyle({
					position:'absolute',
					left:Math.floor((viewportDim.width - popUpImageDim.width)/ 2)+'px',
					top:Math.floor((viewportDim.height - popUpImageDim.height)/ 2)+'px',
					zIndex:101
				}).insert(
					clonedImageFull.setStyle({
						position:'relative',
						backgroundPosition:"-"+Math.floor(rect.x * this.imageRatio.x)+'px -'+Math.floor(rect.y * this.imageRatio.y)+'px',
						left:0,
						top:0,
						width:popUpImageDim.width+'px',
						height:popUpImageDim.height+'px'
					}).show()
				).insert(
					new Element('span').insert("Click Anywhere to Return")
				)
			);
		}
		else if (this.map.popUpClicked) {
			this.map.popUpClicked = false;
			this.overlay.remove();
			this.popUp.remove();
			this.mouseMove(e);
		}
	}
});

var Flyer = Class.create(Enumerable, {  
	initialize:function() {
		var args = $A(arguments);
		if (!args.all(function(arg) {return arg instanceof Page}))
			throw "ImageMap must take an InfoRect as an argument."
		
		this.pages = args;
		this.lastPageIndex = this.pages.size() - 1;
		this.curIndex = 0;
	},
	build:function(parent) {
		if (!Object.isElement(parent))
			throw "Arugment 'parent' must be an element";
		
		this.flyerFrame = new Element('div');
		
		for (i=0;i<=this.lastPageIndex;i++) {
			this.pages[i].build(this.flyerFrame);
		}
		
		parent.appendChild(this.flyerFrame);
		
		Event.observe(window, 'resize', this.setCurrentOffset.bind(this));
		Event.observe(window, 'scroll', this.setCurrentOffset.bind(this));
	},
	setCurrentOffset:function() {
		this.pages[this.curIndex].setOffset();
		
		if (this.pages[this.curIndex].overlay) {
			var viewportDim = document.viewport.getDimensions();
			var scrollOffsets = document.viewport.getScrollOffsets();
		
			this.pages[this.curIndex].overlay.setStyle({
				width:viewportDim.width+'px',
				height:viewportDim.height+'px',
				left:scrollOffsets.left+'px',
				top:scrollOffsets.top+'px'
			});
		}
	},
	getPage:function(action) {
		this.pages[this.curIndex].hide();
		this.pages[this.curIndex].stopObservers();
	
	
		if (action == 'first')
			this.curIndex=0;
		if (action == 'last')
			this.curIndex=this.lastPageIndex;
		if (action == 'previous' && this.curIndex > 0)
			this.curIndex--;
		if (action == 'next' && this.curIndex < this.lastPageIndex)
			this.curIndex++;
			
		this.pages[this.curIndex].show();
		this.updateControls();
		this.pages[this.curIndex].setOffset();
		this.pages[this.curIndex].startObservers();
	},
	updateControls:function() {
		if (this.lastPageIndex == 0) { // Only one page
			$('previousControl').hide();
			$('nextControl').hide();
		}
		else if (this.curIndex == 0) {
			$('previousControl').hide();
			$('nextControl').show();
		}
		else if (this.curIndex == this.lastPageIndex) {
			$('previousControl').show();
			$('nextControl').hide();
		}
		else {
			$('previousControl').show();
			$('nextControl').show();
		}
	}
});

function debug(message) {
	$('debug').update(message);
}

function getTime() {
	var now = new Date();
	return now.getTime();
}
