var Sheer = new Class({
	defaultOptions: function() {
		return {
			container: document,
			eyeRadius: 192,
			pupilRadius: 50,
			norm: "l1",

			onEyeOver: Class.empty,
			onEyeOut: Class.empty,
			onPupilOver: Class.empty,
			onPupilOut: Class.empty
		};
	},

	initialize: function(elements, options) {
		this.setOptions(this.defaultOptions(), options);
		this.imgs = elements;
		this.imgs.each(function(obj, i) {
			obj.setStyles({
				opacity: this.options.opacity
			});
		}.bind(this));

		this.options.container.addEvent("mousemove", function(event){
			event = new Event(event);
			this._animate(event);
		}.bind(this));
	},

	_animate: function(event) {
		this.imgs.each(function(obj, i) {
			var h = this._getDistance(event, obj);
			var objProperties = this._getOpacity(h);
			obj.setStyles({
				opacity: objProperties.currOpacity
			});

			if(h < this.options.eyeRadius) {
				this.fireEvent("onEyeOver", obj, 20);
			} else {
				this.fireEvent("onEyeOut", obj, 20);
			}

			/* if(h < this.options.pupilRadius) {
				this.fireEvent("onPupilOver", obj, 20);
			} else {
				this.fireEvent("onPupilOut", obj, 20);
			} */
		}.bind(this));
	},

	_getDistance: function(event, obj) {
		var objProperties = obj.getCoordinates();
		var curProperties = {
			x: event.page.x,
			y: event.page.y
		};
		objProperties.center = {
			x: (objProperties.left + (objProperties.width / 2)),
			y: (objProperties.top + (objProperties.height / 2))
		};
		switch(this.options.norm) {
			case "l2":
				return Math.round(Math.sqrt(Math.pow((curProperties.x - objProperties.center.x), 2) + Math.pow((curProperties.y - objProperties.center.y),2)));
				break;
			default:
				return Math.abs(curProperties.x - objProperties.center.x) + Math.abs(curProperties.y - objProperties.center.y);
				break;
		};
	},

	_getOpacity: function(h) {
		if(h < this.options.eyeRadius) {
			var currOpacity = (((this.options.opacity - 1) / this.options.eyeRadius) * h) + 1;
			// var height = (((this.options.dimThumb.height - this.options.dimFocus.height) / this.options.eyeRadius) * h) + this.options.dimFocus.height;
		} else {
			var currOpacity = this.options.opacity;
		}
		return {currOpacity:currOpacity};
	}
});
Sheer.implement(new Events);
Sheer.implement(new Options);

/* Special for moving map; ToDo: combine with Sheer class */
var Movingmap = new Class({
	getOptions: function(){
		return {
			onShow: function(el){
				el.effect('opacity',{duration: this.options.duration}).start(1);
			},
			onHide: function(el){
				el.effect('opacity',{duration: this.options.duration*2}).start(this.options.opacity);
			},
			duration: 500,
			opacity: 0,
			showDelay: 6,
			hideDelay: 6
		};
	},

	initialize: function(element, options){
		this.setOptions(this.getOptions(), options);
		this.element = element;
		this.mapImage = element.getChildren()[0];
		element.addEvent('mouseover', function(event){
			this.start(element);
		}.bindWithEvent(this));
		element.addEvent('mouseout', this.end.bindWithEvent(this));
		element.addEvent('mousemove', this.locate.bindWithEvent(this));
		this.end(element);
	},

	start: function(el){
		$clear(this.timer);
		this.timer = this.show.delay(this.options.showDelay, this);
	},
	end: function(event){
		$clear(this.timer);
		this.timer = this.hide.delay(this.options.hideDelay, this);
		if(event.stop){event.stop()};
	},
	locate: function(event){
		/* var win = {'x': window.getWidth(), 'y': window.getHeight()}; */
		/* var scroll = {'x': window.getScrollLeft(), 'y': window.getScrollTop()}; */
		var map = {'x': this.mapImage.offsetWidth/1.2, 'y': this.mapImage.offsetHeight/2.2};
		var prop = {'x': 'left', 'y': 'top'};
		for (var z in prop){
			var pos = event.page[z]; /* + this.options.offsets[z]; */
			/* if ((pos + map[z] - scroll[z]) > win[z]) */ pos = event.page[z] - map[z]; /* - this.options.offsets[z] */
			pos *= -1;
			this.mapImage.setStyle(prop[z], pos + 'px');
		};
		event.stop();
	},

	show: function(){
		this.fireEvent('onShow', [this.element]);
	},
	hide: function(){
		this.fireEvent('onHide', [this.element]);
	}
});
Movingmap.implement(new Events);
Movingmap.implement(new Options);