/* ************************************************************************************* *\
 * The MIT License
 * Copyright (c) 2007 Fabio Zendhi Nagao - http://zend.lojcomm.com.br
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this
 * software and associated documentation files (the "Software"), to deal in the Software
 * without restriction, including without limitation the rights to use, copy, modify,
 * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to the following
 * conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all copies
 * or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 * 
\* ************************************************************************************* */

var iCarousel = new Class({
	options: {
		animation: {
			type: "fadeNscroll",// fadeNscroll, scroll, fade
			direction: "left",// if type = scroll, set: top || left
			amount: 1,// if type = scroll, set the amount to scroll
			transition: Fx.Transitions.Cubic.easeInOut,
			duration: 500,
			rotate: {
				type: "manual",// auto || manual
				interval: 5000,// if type = auto, set the interval (ms)
				onMouseOver: "stop"// if type = auto, set the onmouseover behavior: stop || proceed
			}
		},

		item: {
			klass: "item",
			size: 100
		},

		idPrevious: "previous",
		idNext: "next",
		idToggle: "toggle",

		onClickPrevious: Class.empty,
		onClickNext: Class.empty,
		onPrevious: Class.empty,
		onNext: Class.empty,
		onGoTo: Class.empty
	},

	initialize: function(container, options) {
		this.setOptions(options);
		this.container = $(container);
		this.aItems = $A($$('.'+ this.options.item.klass));
		this.isMouseOver = false;

		if(this.options.idPrevious != "undefined" && $(this.options.idPrevious))
			$(this.options.idPrevious).addEvent("click", function(event) {
				new Event(event).stop();
				this._previous();
				this.fireEvent("onClickPrevious", this, 20);
			}.bind(this));// check if value is not "undefined" before start search the dom with $()
		if(this.options.idNext != "undefined" && $(this.options.idNext))
			$(this.options.idNext).addEvent("click", function(event) {
				new Event(event).stop();
				this._next();
				this.fireEvent("onClickNext", this, 20);
			}.bind(this));
		if(this.options.idToggle != "undefined" && $(this.options.idToggle))
			$(this.options.idToggle).addEvent("click", function(event) {new Event(event).stop(); this._toggle()}.bind(this));

		var oAn = this.options.animation; // short hand
		
	    this.aItems = $A($$('.'+ this.options.item.klass));
	    this.aItems.each(function(item) {
		    item.addEvents({
			    "mouseenter": function() {
				    this.isMouseOver = true;
				    if(this.options.animation.rotate.type == "auto") this.timer = $clear(this.timer);
			    }.bind(this),
			    "mouseleave": function() {
				    this.isMouseOver = false;
				    if(this.options.animation.rotate.type == "auto") this.timer = this._autoRotate.periodical(this.options.animation.rotate.interval, this);
			    }.bind(this)
		    });
	    }.bind(this));
	    this.fx = this.container.effects({duration: oAn.duration, transition: oAn.transition, wait: false});
        this.atScreen = 0;
	    this.container.setStyle(oAn.direction, - this.atScreen * this.options.item.size);

		if(this.options.animation.rotate.type == "auto") this.timer = this._autoRotate.periodical(this.options.animation.rotate.interval, this);
	},

	goTo: function(n) {
        this.atScreen = Math.abs(n % (this.aItems.length));
        this._animate(this.atScreen);
		this.fireEvent("onGoTo", this, 20);
	},

	_previous: function() {
        var from, to;
        from = this.atScreen;
        to = from - this.options.animation.amount;
        
	    this.atScreen = (to >= 0) ? to : 0;
	    this._animate(this.atScreen);
	    this.fireEvent("onPrevious", this, 20);
	},

	_next: function() {
	    var from, to;
        from = this.atScreen;
        to = from + this.options.animation.amount;
        
        var items = {
            total: this.aItems.length,
            visible: this.container.getParent().getStyle('width').toInt() / this.options.item.size
        }
        
        if( to >= (items.total - items.visible) ) {
            this.atScreen = (this.options.animation.rotate.type == "manual") ? (items.total - items.visible) : 0;
        } else {
            this.atScreen = to;
        }
        
	    this._animate(this.atScreen);
	    this.fireEvent("onNext", this, 20);
	},

	_toggle: function() {
		(this.container.getStyle("height").toInt() == 0) ?
			this.container.effect("height", { duration:1000, transition: Fx.Transitions.Sine.easeInOut }).start(this.height):
			this.container.effect("height", { duration:1000, transition: Fx.Transitions.Sine.easeInOut }).start(0);
	},

	_autoRotate: function() {
		if(this.options.animation.rotate.onMouseOver == "stop" && !this.isMouseOver) this._next();
	},

	_animate: function(a, b) {
        var that = this;
		if(that.options.animation.direction == "top") {
			that.fx.start({"opacity":0.75}).chain(function() {
				that.fx.start({"top" : - a * that.options.item.size}).chain(function() {
					that.fx.start({"opacity": 1});
				});
			});
		} else {
			that.fx.start({"opacity":0.75}).chain(function() {
				that.fx.start({"left" : - a * that.options.item.size}).chain(function() {
					that.fx.start({"opacity": 1});
				});
			});
		}
	}
});
iCarousel.implement(new Events); // Implements addEvent(type, fn), fireEvent(type, [args], delay) and removeEvent(type, fn)
iCarousel.implement(new Options);// Implements setOptions(defaults, options)

