(function() {

	SL.effects.ContentChanger = Class.create(SL.Component, {

		init : function() {
			this.config.setDefault('timeout', 5000);
			this.config.setDefault('duration', 500);

			this.content = this.config.get('content');
			this.current = 0;

			this.mode = this.config.get('mode');

			if (this.content.length <= 1) {
				return;
			}

			if (this.mode == 'slideshow_horizontal') {
				this.count = this.config.get('count');
				if (this.content.length < this.count) {
					return;
				}
				this.current = 0;
				this.contentDiv = this.e.down('.slideshow_horizontal_content_inner');

				this.leftBtn = this.e.down('.slideshow_horizontal_left');
				if (this.leftBtn) {
					this.leftBtn.observe('click', this.onPrev.bind(this));
					this.leftBtn.addClassName('disabled');
				}

				this.rightBtn = this.e.down('.slideshow_horizontal_right');
				if (this.rightBtn) {
					this.rightBtn.observe('click', this.onNext.bind(this, false));
					if (this.current >= this.content.length - this.count) {
						this.rightBtn.addClassName('disabled');
					}
				}
				if (this.config.get('autostart')) {
					this.startSlideshow.bind(this).defer();
				}
			} else if (this.mode == 'slideshow_horizontal_auto_left_right') {
				this.contentDiv = this.e.down('.slideshow_horizontal_content_inner');
				this.horizontalTimer = setTimeout(this.nextHorizontalAuto.bind(this, true), this.config.get('timeout'));
			} else if (this.mode == 'slideshow_horizontal_auto_right_left') {
				this.contentDiv = this.e.down('.slideshow_horizontal_content_inner');
				this.rl = true;
				this.horizontalTimer = setTimeout(this.nextHorizontalAuto.bind(this, true), this.config.get('timeout'));
			} else {
				this.currentElement = $(this.content[0].id);
				if (this.config.get('timeout') > 0) {
					setTimeout(this.next.bind(this, true), this.content[0].timeout || this.config.get('timeout'));
				}
			}

			this.nav = this.e.down('.content_changer_nav');
			if (this.nav) {
				var zIndex = this.nav.up().findZIndex() || 0;
				this.nav.setStyle({
					zIndex : (zIndex + 5) + ''
				});

				this.nav = this.nav.down().childElements();
				this.nav[0].addClassName('active');
				for ( var i = 0; i < this.nav.length; i++) {
					this.nav[i].observe('click', this.switchTo.bind(this, i));
					this.nav[i].setStyle({
						cursor : 'pointer'
					});
				}
			}

			this.e.select('.content_changer_next').each(function(e) {
				e.observe('click', this.next.bind(this, false));
			}.bind(this));

			this.e.select('.content_changer_prev').each(function(e) {
				e.observe('click', this.prev.bind(this, false));
			}.bind(this));

			this.mouseOverCSS = this.config.get('mouse_over_css');
			if (this.mouseOverCSS) {
				this.e.observe('mouseenter', this.mouseOverEnter.bind(this));
				this.e.observe('mouseleave', this.mouseOverLeave.bind(this));
				this.e.select('.' + this.mouseOverCSS).each(function(e) {
					e.hide();
				}.bind(this));
			}
		},

		mouseOverEnter : function() {
			this.e.select('.' + this.mouseOverCSS).each(function(e) {
				SL.effects.registerCurrent(Effect.Appear(e, {
					duration : 0.25
				}));
			}.bind(this));
		},

		mouseOverLeave : function() {
			this.e.select('.' + this.mouseOverCSS).each(function(e) {
				SL.effects.registerCurrent(Effect.Fade(e, {
					duration : 0.25
				}));
			}.bind(this));
		},

		startSlideshow : function() {
			this.autostart = true;
			this.onNext(true);
		},

		next : function(automatic) {
			if (this.disabled) {
				return;
			}
			if (automatic || !this.hasAnimation) {
				if (!automatic && this.timeout) {
					clearTimeout(this.timeout);
					this.timeout = undefined;
					this.userNavigation = true;
				}
				this.current++;
				if (this.current >= this.content.length) {
					this.current = 0;
				}

				var e = $(this.content[this.current].id);
				if (!e) {
					console.log("Unable to get element for id:", this.content[this.current].id);
					this.switchToCurrent.bind(this).defer();
					return;
				}

				new SL.effects.Preloader(e, this.switchToCurrent.bind(this)).run();
			}
		},

		prev : function(automatic) {
			if (this.disabled) {
				return;
			}
			if (automatic || !this.hasAnimation) {
				if (!automatic && this.timeout) {
					clearTimeout(this.timeout);
					this.timeout = undefined;
					this.userNavigation = true;
				}
				this.current--;
				if (this.current < 0) {
					this.current = this.content.length - 1;
				}
				new SL.effects.Preloader($(this.content[this.current].id), this.switchToCurrent.bind(this)).run();
			}
		},

		switchTo : function(i) {
			if (this.disabled) {
				return;
			}
			if (!this.hasAnimation && this.current != i) {
				if (this.mode == 'slideshow_horizontal_auto_right_left' || this.mode == 'slideshow_horizontal_auto_left_right') {
					this.switchToHorizontal(i);
					return;
				}

				if (this.timeout) {
					clearTimeout(this.timeout);
					this.timeout = undefined;
					this.userNavigation = true;
				}
				this.current = i;
				new SL.effects.Preloader($(this.content[this.current].id), this.switchToCurrent.bind(this)).run();
			}
		},

		switchToCurrent : function() {

			if (this.hasAnimation || this.disabled) {
				return;
			}

			this.hasAnimation = true;

			var zIndex = this.currentElement.up().findZIndex() || 0;

			this.currentElement.setStyle({
				zIndex : zIndex + ''
			});

			var duration = this.config.get('duration');

			new Effect.Fade(this.currentElement, {
				from : 1.0,
				to : 0.0,
				duration : duration / 2000.0,
				transition : Effect.Transitions.linear,
				delay : duration / 2000.0
			});

			this.currentElement = $(this.content[this.current].id);

			this.currentElement.setOpacity(0.0);
			this.currentElement.setStyle({
				visibility : 'visible',
				zIndex : (zIndex + 1) + ''
			});

			new Effect.Appear(this.currentElement, {
				from : 0.0,
				to : 1.0,
				duration : duration / 1000.0,
				transition : Effect.Transitions.linear,
				afterFinish : function() {
					this.hasAnimation = false;
					this.activateTimeout();
				}.bind(this)
			});

			if (this.nav) {
				setTimeout(this.updateNav.bind(this), duration / 2);
			}
		},

		updateNav : function() {
			this.nav.each(function(e) {
				e.removeClassName('active');
			});
			this.nav[this.current].addClassName('active');
		},

		activateTimeout : function() {
			if (!this.userNavigation && this.config.get('timeout') > 0) {
				this.timeout = setTimeout(this.next.bind(this, true), this.content[this.current].timeout || this.config.get('timeout'));
			}
		},

		onNext : function(auto) {
			if (this.disabled) {
				return;
			}

			if (this.hasAnimation) {
				if (!auto) {
					this.autostart = undefined;
				}
				return;
			}
			if (this.current >= this.content.length - this.count) {
				if (auto) {
					this.autostart = undefined;
				}
				return;
			}

			if (!auto) {
				this.autostart = undefined;
			}

			this.hasAnimation = true;
			this.current += this.count;
			if (this.current >= this.content.length - this.count) {
				this.current = this.content.length - this.count;
				if (this.rightBtn) {
					this.rightBtn.addClassName('disabled');
				}
			} else {
				if (this.rightBtn) {
					this.rightBtn.removeClassName('disabled');
				}
			}

			if (this.current > 0) {
				if (this.leftBtn) {
					this.leftBtn.removeClassName('disabled');
				}
			}

			this.scrollToCurrent(true);
		},

		onPrev : function() {
			if (this.disabled) {
				return;
			}

			if (this.hasAnimation) {
				this.autostart = undefined;
				return;
			}
			if (this.current <= 0) {
				return;
			}

			this.autostart = undefined;

			this.hasAnimation = true;
			this.current -= this.count;
			if (this.current <= 0) {
				this.current = 0;
				if (this.leftBtn) {
					this.leftBtn.addClassName('disabled');
				}
			} else {
				if (this.leftbtn) {
					this.leftBtn.removeClassName('disabled');
				}
			}

			if (this.current < this.content.length - this.count) {
				if (this.rightBtn) {
					this.rightBtn.removeClassName('disabled');
				}
			}

			this.scrollToCurrent(false);
		},

		scrollToCurrent : function(auto) {
			if (this.disabled) {
				return;
			}

			var newX = $(this.content[this.current].id).positionedOffset().left;

			new Effect.Move(this.contentDiv, {
				x : newX * -1,
				y : 0,
				mode : 'absolute',
				duration : this.config.get('duration') / 1000.0,
				transition : auto ? Effect.Transitions.linear : Effect.Transitions.sinoidal,
				afterFinish : function() {
					this.hasAnimation = false;
					if (this.autostart) {
						this.onNext(true);
					}
				}.bind(this)
			});
		},

		nextHorizontalAuto : function() {
			this.switchToHorizontal(this.current + 1);
		},

		switchToHorizontal : function(nextIndex) {

			if (this.hasAnimation || this.disabled) {
				return;
			}

			if (this.horizontalTimer) {
				clearTimeout(this.horizontalTimer);
				this.horizontalTimer = undefined;
			}

			var old = $(this.content[this.current].id);

			this.current = nextIndex;

			if (this.current > this.content.length - 1) {
				this.current = 0;
			}

			var next = $(this.content[this.current].id);
			var width = this.contentDiv.getWidth();

			this.hasAnimation = true;

			var finishCB = function() {
				this.hasAnimation = false;
				this.horizontalTimer = setTimeout(this.nextHorizontalAuto.bind(this, true), this.config.get('timeout'));
			}.bind(this);

			if (this.rl) {
				next.setStyle({
					left : (width) + 'px'
				});

				next.show();

				new Effect.Move(next, {
					x : -width,
					mode : 'relative',
					duration : this.config.get('duration') / 1000.0,
					afterFinish : finishCB
				});
				new Effect.Move(old, {
					x : -width,
					mode : 'relative',
					duration : this.config.get('duration') / 1000.0
				});
			} else {
				next.setStyle({
					left : (-1 * width) + 'px'
				});

				next.show();

				new Effect.Move(next, {
					x : width,
					mode : 'relative',
					duration : this.config.get('duration') / 1000.0,
					afterFinish : finishCB
				});
				new Effect.Move(old, {
					x : width,
					mode : 'relative',
					duration : this.config.get('duration') / 1000.0
				});
			}

			if (this.nav) {
				setTimeout(this.updateNav.bind(this), this.config.get('duration') / 2);
			}
		},

		cleanup : function() {
			this.disabled = true;
		}
	});

	SL.effects.ImageMagnifier = Class.create(SL.Element, {

		init : function() {

			this.config.setDefault('position', 'none');

			this.url = this.config.get('url');
			this.attachElement = $(this.config.get('attach_id'));

			var loader = new Image();

			loader.onload = function() {
				this.initView.bind(this, loader.width, loader.height).defer();
			}.bind(this);

			loader.src = this.url;

			this.box = new Element('div');
			this.box.setStyle({
				position : 'absolute',
				backgroundColor : '#fff'
			});
			this.box.setOpacity(0.3);

			this.box.hide();

			this.attachElement.up().appendChild(this.box);

			this.attachElement.up().setStyle({
				position : 'relative'
			});

			var top = new Element('div');
			this.attachElement.up().appendChild(top);
			top.setStyle({
				position : 'absolute',
				left : 0,
				top : 0,
				width : this.attachElement.getWidth() + 'px',
				height : this.attachElement.getHeight() + 'px'
			});

			top.observe('mouseenter', this.onMouseEnter.bind(this));
			top.observe('mouseleave', this.onMouseLeave.bind(this));
			top.observe('mousemove', this.onMouseMove.bind(this));
		},

		initView : function(width, height) {

			var aspect = this.attachElement.getWidth() / this.attachElement.getHeight();
			var testWidth = height * aspect;
			// var testHeight = width * aspect;

			var boxWidth = this.e.getWidth() / width * this.attachElement.getWidth();
			var boxHeight = this.e.getHeight() / height * this.attachElement.getHeight();

			if (testWidth < width) {
				var add = (width / this.attachElement.getWidth() * boxWidth);
				this.width = width + add;
				this.height = (width / aspect) + add;
			} else {
				var add = (height / this.attachElement.getHeight() * boxHeight);
				this.width = (height * aspect) + add;
				this.height = height + add;
			}

			this.box.setStyle({
				width : boxWidth + 'px',
				height : boxHeight + 'px'
			});

			this.e.down().down().setStyle({
				position : 'absolute',
				top : 0,
				left : 0,
				width : this.width + 'px',
				height : this.height + 'px',
				backgroundImage : 'url(' + this.url + ')'
			});
		},

		onMouseEnter : function(e) {

			var position = this.config.get('position');

			if (position == 'right') {
				this.e.setStyle({
					position : 'absolute',
					marginLeft : this.attachElement.getWidth() + 'px',
					top : 0
				});
			}

			this.setPosition(e.pageX, e.pageY);
			this.e.show();
			this.box.show();
		},

		onMouseLeave : function(e) {
			this.e.hide();
			this.box.hide();
		},

		onMouseMove : function(e) {
			this.setPosition(e.pageX, e.pageY);
		},

		setPosition : function(x, y) {

			var offset = this.attachElement.cumulativeOffset();

			var width = this.attachElement.getWidth();
			var height = this.attachElement.getHeight();

			var px = x - offset.left;
			var py = y - offset.top;

			var boxWidth = this.box.getWidth();
			var boxHeight = this.box.getHeight();

			if (px < boxWidth / 2) {
				px = boxWidth / 2;
			} else if (px > width - boxWidth / 2) {
				px = width - boxWidth / 2;
			}

			if (py < boxHeight / 2) {
				py = boxHeight / 2;
			} else if (py > height - boxHeight / 2) {
				py = height - boxHeight / 2;
			}

			this.box.setStyle({
				left : (px - boxWidth / 2) + 'px',
				top : (py - boxHeight / 2) + 'px'
			});

			var x1 = (this.width - this.e.getWidth()) * (px / width * -1.0);
			var y1 = (this.height - this.e.getHeight()) * (py / height * -1.0);

			this.e.down().down().setStyle({
				left : x1 + 'px',
				top : y1 + 'px'
			});
		}

	});

})();

