// ------------------------------------------------------
//	Carousel v1.0
//	by MrkEw NET
//  using Prototype Framework http://www.prototypejs.org
//        Scriptaculous Effects http://script.aculo.us/
// ------------------------------------------------------
var Carousel = Class.create();
Carousel.prototype = {

    cEl:null,
    cBox:null,
    itemClass:null,

    prevButton:null,
    nextButton:null,

    scrollInc:1,

    items:null,
    itemWidth:0,
    itemActual:0,
    itemsCount:0,
    itemsVisible:0,
    isMoreVisible:false,

    lastItemMove:0,
    lastDir:null,

    moveDur:.5,
    fadeDur:.25,

    circular:false,
    vertical:false,

    autoRun:false,
    autoRunStop:false,
    autoRunTimeout:null,
    autoRunDir:1,
    autoRunFreq:3,

    initInt:null,

    initialize: function(carouselID, scrollBoxID, carouselItemClass, buttons, opt) {
        this.itemClass = carouselItemClass;
        this.cEl = $(carouselID);
        this.cBox = $(scrollBoxID);
        this.items = $$("#"+scrollBoxID+" ."+this.itemClass);
        if (this.items.length==0) return;

        if (opt!=null) {
            if (opt.vertical!=null && opt.vertical) this.vertical=opt.vertical;
            if (opt.autoRun!=null && opt.autoRun) this.autoRun=opt.autoRun;
            if (opt.autoRunDir!=null && opt.autoRunDir==-1) this.autoRunDir=-1;
            if (opt.autoRunFreq!=null && parseFloat(opt.autoRunFreq)>0) this.autoRunFreq=opt.autoRunFreq;
            if (opt.circular!=null && opt.circular) this.circular=opt.circular;
            if (opt.scrollInc!=null && parseInt(opt.scrollInc)>0) this.scrollInc=parseInt(opt.scrollInc);
            if (opt.duration!=null && parseFloat(opt.duration)>0) {
                this.moveDur = parseInt(opt.duration*10/2)/10;
                this.fadeDur = parseInt(opt.duration*10/4)/10;
                   if (this.autoRun && this.autoRunFreq<opt.duration)
                       this.autoRunFreq = opt.duration;
               }
        }

        this.prevButton = $(buttons.prev);
        this.nextButton = $(buttons.next);

        if (this.isVisible())
            this.init();
        else
            this.initInt=self.setInterval( (function() { if (this.isVisible()) { self.clearInterval(this.initInt); this.init(); } }).bind(this), 500);
    },
    isVisible:function() {
        var go = true;
        this.cBox.ancestors().each(function(node) { if (go) go=node.visible() });
        return go;
    },
    init:function() {
        this.itemsCount = this.items.length;
        this.itemWidth = this.vertical ? this.items[0].getHeight() : this.items[0].getWidth();

        var opt = { width: (this.itemWidth * this.items.length) + "px" };
        if (this.vertical)
            opt  = { height: (this.itemWidth * this.items.length) + "px" };

        this.cBox.setStyle(opt);

        var bwp = $(this.cBox.parentNode), blw=parseInt(this.vertical ? bwp.getStyle("borderUpWidth") : bwp.getStyle("borderLeftWidth")), brw=parseInt(this.vertical ? bwp.getStyle("borderBottomWidth") : bwp.getStyle("borderRightWidth")), br = (isNaN(blw) ? 0 : blw) + (isNaN(brw) ? 0 : brw), bw = (this.vertical ? bwp.getHeight() : bwp.getWidth()) - br, n = bw / this.itemWidth;
        this.itemsVisible = parseInt(n);

        if (this.itemsVisible>this.itemsCount) {
            this.prevButton.addClassName("disabled");
            this.nextButton.addClassName("disabled");
            return;
        }

        this.isMoreVisible = (Math.ceil(n*10)/10)>this.itemsVisible;
        this.lastItemMove = ((n *10) % 10 == 0) ? this.itemWidth : this.itemWidth - (bw - (this.itemsVisible * this.itemWidth));

        if (this.scrollInc>this.itemsVisible) this.scrollInc=this.itemsVisible;

        this.prevButton.dirt = -1;
        this.nextButton.dirt = 1;

        this.listen();

        if (this.autoRun) {
            var C = this;
            self.setTimeout(function() {C.slideIt()}, this.autoRunFreq * 1000);
        }
    },
    listen:function() {
        this.prevButton.observe("click", (function(event) { this.move(event); }).bind(this));
        this.nextButton.observe("click", (function(event) { this.move(event); }).bind(this));
    },
    stopListen:function() {
        this.prevButton.stopObserving("click");
        this.nextButton.stopObserving("click");
    },
    move:function(e) {
        var el=Event.element(e);
        this.makeMove(el.dirt);
        this.autoRunStop=true;
        var C = this;
        clearTimeout(this.autoRunTimeout);
        this.autoRunTimeout = self.setTimeout(function() {C.restart()}, 3 * this.autoRunFreq * 1000);
        Event.stop(e);
        return false;
    },
    makeMove:function(dir) {
//        if (!this.isVisible())
//            return false;

        this.stopListen();

        var move = dir * this.scrollInc;

        var r = (dir>0) ? this.itemsCount-this.itemsVisible-this.itemActual: this.itemActual;
        var a = (this.circular) ? this.itemActual + move : this.itemActual + (r!=0 && r<this.scrollInc ? dir*(r) : move);
        if (a>=0 && (a+this.itemsVisible)<=this.itemsCount)
            return this.switchSlide(a-this.itemActual, dir, a);

        else if (this.circular) {
            var n,  m=Math.abs(move)-r;
            for (var i=0; i<m; i++) {
                n = (dir<0) ? this.itemsCount-m+i : i;
                this.cBox.removeChild(this.items[n]);
                if (dir<0)
                    this.cBox.insertBefore(this.items[n], this.items[0]);
                else
                    this.cBox.appendChild(this.items[n]);
            }

            var w = this.isMoreVisible && this.itemActual!=0 ? this.lastItemMove : this.itemWidth, lft = (dir<0) ? -(((this.scrollInc-1) * this.itemWidth) + w) : -((this.itemsCount - this.itemsVisible - this.scrollInc-1) * this.itemWidth + w);
            this.items = $$("#"+this.cBox.id+" ."+this.itemClass);

            var pos = this.vertical ? {top: lft+"px" } : {left: lft+"px" };
            this.cBox.absolutize().setStyle(pos).relativize();

            return this.switchSlide(move, dir, (dir<0) ? 0 : this.itemActual + r);
        }

        this.listen();
        return false;
    },
    switchSlide:function(move, dir, a) {
        var w = this.itemWidth;
        if (!(this.lastDir==null && dir<0) && (this.lastDir!=dir || (this.lastDir!=dir && dir<0 && this.itemActual!=0)))
            w = this.lastItemMove;

        var C = this;
        var opt = { x: -dir*((Math.abs(move)-1)*this.itemWidth + w), y: 0, mode: "relative", duration: this.moveDur, queue: "end" };
        if (this.vertical) {
            opt.x = 0;
            opt.y = -dir*((Math.abs(move)-1)*this.itemWidth + w);
        }

        new Effect.Fade(this.cBox, { duration: this.fadeDur, from: 1, to: .7, queue: "end" } );
        new Effect.Move(this.cBox, opt);
        new Effect.Fade(this.cBox, { duration: this.fadeDur, from: .8, to: 1, afterFinish: function(){ C.listen(); }, queue: "end" } );

        this.itemActual = a;
        this.lastDir=dir;
        return true;
    },
    slideIt:function() {
        if (this.autoRun && !this.autoRunStop) {
            while (!this.makeMove(this.autoRunDir))
                this.autoRunDir = this.autoRunDir * -1;
            var C = this;
            self.setTimeout(function() {C.slideIt()}, this.autoRunFreq * 1000);
        }
    },
    restart:function() {
        this.autoRunStop=false;
        this.autoRunDir=this.lastDir;
        this.slideIt();
    }
}
