EaseOutExpo = function (pos) {
    return (-Math.pow(2, -10*pos)+1);
};

EaseInExpo = function (pos) {
    return Math.pow(2, 10*(pos-1));
};

EaseInOutExpo = function (pos) {
    return (-Math.pow(2, -10*pos)+1);
};

// Slide = function (idx, btn) {
//     this.x = x;
//     this.y = y;
// };
// 
// Slide.prototype.__repr__ = function () {
// };
// 
// Slide.prototype.toString = function () {
//     return this.__repr__();
// };

Slides = {
    _move: null,
    _move2: null,
    _down: null,
    _offset: null,
    _anim: null,
    
    _slides: new Array(),
    _slideContainer: null,
    _numSlides: 0,
    _currentSlide: 0,
    _slideWidth: 640,
    _slideMargin: 50,
    _slideHeight: 480,
    _slideThreshold: 640/5,
    _buttons: null,
    _titleEl:null,
    _slideEls:null,
    _slideAnimOptions: null,
    _fadeAnimOptions: null,
    _fadeAnim: null,
    _showingInstruction: true,
    _deletdInstruction: false,
    
    
    setup: function (container, elems, buttons, titleEl) {
        hideElement('load-counter');
        
        Slides._slideContainer = container;
        Slides._buttons = buttons;
        Slides._titleEl = titleEl;
        Slides._slideEls = elems;
        log(Slides._slideContainer);

        var i = 0;
        
        forEach(elems,
            function(elem) {
                Slides._slides.push(elem);
                setElementPosition(elem,
                                   new MochiKit.Style.Coordinates(Slides._offsetFor(i),
                                                                  0)
                                  );
                if (i>0) {
                    connect(getElement('slide-navi-link-' + (i-1)),
                            'onclick',
                            partial(Slides.goSlide, i));
                }
                i++;
            });
        Slides._numSlides = i;
        
        
        Slides._slideAnimOptions = {    duration: 1.5,
                                        fps: 30,
                                        transition: EaseInOutExpo,
                                        afterFinish: Slides._afterSlide
                                    };
        Slides._move2 = connect(document, 'onmousemove', Slides._moved);
        hideElement('slide-arrow-left');
        Slides._fadeAnimOptions = {duration:0.5, 'to':0, 'from':1, sync:true};
        connect('slide-arrow-left', 'onclick', Slides.prevSlide);
        connect('slide-arrow-right', 'onclick', Slides.nextSlide);
        connect('content', 'onselectstart', function (e) {
            e.stop();
            return false;
        });
        
        connect('content-inner', 'onmousedown', Slides.dragStart);
        
        Slides.centering();
        setElementPosition(Slides._slideContainer,
                           new MochiKit.Style.Coordinates(0,
                                                          0));
        if (elementDimensions('slide-main').h >
            elementDimensions('content').h) {
            try {
                getElement('content').scrollTop = 
                    Math.floor((elementDimensions('slide-main').h - elementDimensions('content').h) / 2);
            } catch(err) {}
        }
            

    },
    
    _afterSlide: function () {
        log('endSlide');
        if (! Slides._deletdInstruction && Slides._currentSlide > 0) {
            removeElement('slide-instruction');
            Slides._deletdInstruction = true;
        }
    },
    
    nextSlide: function (idx) {
        Slides.goSlide(Slides._currentSlide + 1);
    },
    

    prevSlide: function (idx) {
        Slides.goSlide(Slides._currentSlide - 1);
    },
    
    goSlide: function (idx) {
        //if (e) e.preventDefault();
        Slides._disconnect();
        var doCallback = true
        if (Slides._showingInstruction){
            log(idx);
            if (idx < 1) {
                Slides._currentSlide = 0;
            } else {
                Slides._currentSlide = Math.min(idx, Slides._numSlides - 1);
                Slides._showingInstruction = false;        
            }
        } else
            Slides._currentSlide = Math.min(Math.max(1, idx), Slides._numSlides - 1);
            
        if (Slides._currentSlide >= Slides._numSlides -1)
            hideElement('slide-arrow-right');
        else
            showElement('slide-arrow-right');

        if (Slides._currentSlide <= 1)
            hideElement('slide-arrow-left');
        else
            showElement('slide-arrow-left');
        var x = - Slides._offsetFor(Slides._currentSlide);
        forEach(Slides._buttons,
            function(elem) {
            
                if (elem.id == 'slide-navi-button-' + (Slides._currentSlide - 1))
                    elem.src = ON_BULLET.src;
                else
                    elem.src = OFF_BULLET.src;            
            });
        
        if (Slides._titleEl) {
            var title = "\u00a0";
            var titleDiv = getFirstElementByTagAndClassName("div",
                                                 "slide-slide-title", 
                                                 Slides._slideEls[Slides._currentSlide]);
            if (titleDiv)
                title = scrapeText(titleDiv);
            replaceChildNodes(Slides._titleEl, title);
        }

        if (Slides._anim)
            Slides._anim.cancel();
        Slides._anim = MochiKit.Visual.Move(
            Slides._slideContainer,
            MochiKit.Base.setdefault({x:x, y:0, mode:'absolute'}, Slides._slideAnimOptions));
    },
    
    _diff: function(lhs, rhs) {
        return new MochiKit.Style.Coordinates(lhs.x - rhs.x, lhs.y - rhs.y);
    },
    
    _offsetFor: function (idx) {
        return idx * (Slides._slideWidth + Slides._slideMargin);
    },
    
    _indexFor: function (x) {
        return Math.max(0, Math.min(Slides._numSlides - 1, Math.floor(x / (Slides._slideWidth + Slides._slideMargin))));
    },
    
    dragStart: function(e) {
        e.stop();
        Slides._disconnect();
        log("drag start");
        if (Slides._anim)
            Slides._anim.cancel();

        Slides._offset = getElementPosition(e.mouse().page);
        Slides._move = connect('content-inner', 'onmousemove', Slides._drag);
        Slides._down = connect('content-inner', 'onmouseup', Slides._stop);
    },
    
    _disconnect: function () {
        if (Slides._move)
            disconnect(Slides._move);
        if (Slides._down)
            disconnect(Slides._down);
        Slides._move = Slides._down = null;
    },
    
    _drag: function(e) {
        e.stop();
        var amt = Slides._diff(e.mouse().page, Slides._offset);
        if (Math.abs(amt.x) > Slides._slideThreshold) {
            if (amt.x < 0)
                if (Slides._currentSlide == Slides._numSlides -1)
                    Slides.goSlide(Slides._currentSlide);                
                else
                    Slides.nextSlide();
            else {
                if (Slides._currentSlide == 0)
                    Slides.goSlide(Slides._currentSlide);                
                else
                    Slides.prevSlide();
            }
        } else {
            amt.x -=  Slides._offsetFor(Slides._currentSlide);
            amt.y = 0;
            setElementPosition(Slides._slideContainer, amt);
        }
        return false;
    },
    
    _moved: function(e) {
        if (Slides._currentSlide == 0)
            return;
        // alpha on
        Slides._fadeInNavi();
        // timeout cancel
        if (Slides._movedTimer)
            clearTimeout(Slides._movedTimer);
        // timeout on
        Slides._movedTimer = setTimeout(Slides._fadeOutNavi, 500);
        
    },
    
    _fadeInNavi: function (e) {
        if (Slides._fadeAnim)
            Slides._fadeAnim.cancel();
        setOpacity('slide-arrow-left', 1);
        setOpacity('slide-arrow-right', 1);
        setOpacity('slide-navi', 1.0);
    },
    
    _fadeOutNavi: function (e) {
        if (Slides._fadeAnim)
            Slides._fadeAnim.cancel();
        Slides._fadeAnim  = new Parallel([new Opacity('slide-arrow-left',Slides._fadeAnimOptions),
                                          new Opacity('slide-arrow-right',Slides._fadeAnimOptions),
                                          new Opacity('slide-navi',Slides._fadeAnimOptions)]);
    },
    
    _stop: function(e) {
        log('drag stop');
        Slides.goSlide(Slides._currentSlide);
    },
    
    centering: function (e) {
        var slideDiv = getElement('slide-main');
        var r1 = elementDimensions(getElement('content'));
        var r2 = elementDimensions(slideDiv);
        var pos = {x:(r1.w - r2.w)/2, y: Math.max(0, (r1.h - r2.h) / 2)};
        setElementPosition(slideDiv,pos);
    }
};

connect(document, 'onkeydown', 
    function(e) {
        var key = e.key();
        if (key.string == 'KEY_ARROW_RIGHT') {
            e.preventDefault();
            Slides.nextSlide();
        }
        if (key.string == 'KEY_ARROW_LEFT') {
            e.preventDefault();
            Slides.prevSlide();
        }
    });

connect(window, 'onload',
    function() {
        //createLoggingPane(true);
        Slides.setup(getElement('slide-container'),
                     getElementsByTagAndClassName('DIV', 'slide-slide'),
                     getElementsByTagAndClassName('IMG', 'slide-navi-button'),
                     getElement('slide-title')
                    );
        connect(window, 'onresize', Slides.centering);
                
       var alignSlide = function (el) {
           var r2 = elementDimensions(el);
           r2.h += 40;
           var pos = {x:(Slides._slideWidth - r2.w)/2, y: (Slides._slideHeight - r2.h) / 2};
           setElementPosition(el, pos);
           showElement(el);
       };
       
       var slds = getElementsByTagAndClassName('DIV', 'slide-slide-inner');
       forEach(slds,
           function(div) {
                alignSlide(div);
           });
           
       removeElementClass('body', 'loading');
       window.status = 'please drag your mouse or press arrow keys to navigate.';
    });

var NUM_LOADED = 0;

function imageLoaded() {
    ++NUM_LOADED;
    try {
        getElement('load-counter').innerText = 'Loaded ' + NUM_LOADED + ' out of '  + NUM_IMAGES;
    } catch( e ){
    }
}

