
(function(){

    var Dom = YAHOO.util.Dom;
    var Event = YAHOO.util.Event;
    var CustomEvent = YAHOO.util.CustomEvent;
    var Selector = YAHOO.util.Selector;
    
    var IMG = '/site_media/capdigital/img';
    
    /**
     * CapScroller
     */
    window.CapScroller = function(parentEl, config){
        //console.info('CapScroller: new', arguments);
        
        this._parentEl = parentEl;
        
        config = config || {};
        this._config = config;
        this._config.spacing = this._config.spacing || 0;
        this._config.align = this._config.align || 'right';
        
        this._render();
        this._initEvents();
        
        this.update();
    };
    window.CapScroller.prototype = {
    
        _render: function(){
        
            this.contentEl = document.createElement('div');
            this.contentEl.className = 'scroller-container';
            this.contentEl.style.height = this._parentEl.offsetHeight + 'px';
            
            while (this._parentEl.childNodes.length) {
                this.contentEl.appendChild(this._parentEl.childNodes[0])
            }
            this._parentEl.appendChild(this.contentEl);
            
            
            this._scrollerEl = document.createElement('div');
            this._scrollerEl.className = 'scroller';
            this._scrollerEl.innerHTML = '<div class="c1">' +
            '<img src="/site_media/capdigital/img/cap/up_small.png" class="up" />' +
            '<div class="c2">' +
            '<div class="box"></div>' +
            '</div>' +
            '<img src="/site_media/capdigital/img/cap/down_small.png" class="down" />' +
            '</div>';
            this.contentEl.parentNode.appendChild(this._scrollerEl);
            
            this._c1El = Dom.getElementsByClassName('c1', null, this._scrollerEl)[0];
            this._c2El = Dom.getElementsByClassName('c2', null, this._scrollerEl)[0];
            this._boxEl = Dom.getElementsByClassName('box', null, this._scrollerEl)[0];
            
            this._upEl = Dom.getElementsByClassName('up', null, this._scrollerEl)[0];
            this._downEl = Dom.getElementsByClassName('down', null, this._scrollerEl)[0];
            
            
        },
        
        _initEvents: function(){
        
            var scrolling = false;
            var prevY = null;
            
            YAHOO.util.Event.addListener(this._boxEl, 'mousedown', function(e){
                //console.warn('mousedown');
                
                //YAHOO.util.Event.stopPropagation(e);
                //YAHOO.util.Event.preventDefault(e);
                
                scrolling = true;
                prevY = null;
                
            }, null, this);
            
            YAHOO.util.Event.addListener(document.body, 'mouseup', function(){
                scrolling = false;
            }, null, this);
            
            YAHOO.util.Event.addListener(document.body, 'mousemove', function(e){
                //console.warn('mousemove', arguments);
                
                if (!scrolling) 
                    return;
                
                var mouseY = Event.getXY(e)[1];
                
                if (prevY === null) {
                    prevY = mouseY;
                }
                
                var delta = mouseY - prevY;
                var topDelta = Math.floor(delta / parseInt(this._boxEl.offsetHeight, 10) * parseInt(this._c2El.offsetHeight, 10));
                
                this.contentEl.scrollTop += topDelta;
                
                this._updateBox();
                
                prevY = mouseY;
                
            }, null, this);
            
            YAHOO.util.Event.addListener(this._upEl, 'click', function(){
                try {
                    var toScrollTop = this.contentEl.scrollTop - (this.contentEl.offsetHeight / 2);
                    this._animateScroll(toScrollTop);
                } 
                catch (e) {
                    console.error(e);
                }
            }, null, this);
            
            YAHOO.util.Event.addListener(this._downEl, 'click', function(){
                try {
                    var toScrollTop = this.contentEl.scrollTop + (this.contentEl.offsetHeight / 2);
                    this._animateScroll(toScrollTop);
                } 
                catch (e) {
                    console.error(e);
                }
            }, null, this);
            
            YAHOO.util.Event.addListener(this.contentEl, 'DOMMouseScroll', function(e){
                try {
                    YAHOO.util.Event.preventDefault(e);
                    
					var scrollTop = this.contentEl.scrollTop;
					
					if (-e.detail / 3 < 0) {
						this._animateScroll(scrollTop + 120);
                    }
                    else {
						this._animateScroll(scrollTop - 120);
                    }
                    
                } 
                catch (e) {
                    console.error(e);
                }
            }, null, this);
            
            
            
        },
        
        _animateScroll: function(toScrollTop){
        
            if (toScrollTop < 0) 
                toScrollTop = 0;
            
            var maxTop = parseInt(this.contentEl.scrollHeight, 10) - parseInt(this.contentEl.offsetHeight, 10);
            if (toScrollTop > maxTop) 
                toScrollTop = maxTop;
            
			this._scrollAnim &&  this._scrollAnim.stop();
            this._scrollAnim = new YAHOO.util.Scroll(this.contentEl, {
                scroll: {
                    to: [this.contentEl.scrollLeft, toScrollTop]
                }
            }, 0.5, YAHOO.util.Easing.easeOut);
            
            var toBoxTop = (toScrollTop / this.contentEl.scrollHeight) * this._c2El.offsetHeight;
            
			this._boxMoveAnim && this._boxMoveAnim.stop();
			this._boxMoveAnim = new YAHOO.util.Scroll(this._boxEl, {
                top: {
                    to: toBoxTop
                }
            }, 0.5, YAHOO.util.Easing.easeOut);
            
            this._scrollAnim.animate();
            this._boxMoveAnim.animate();
        },
        
        update: function(){
        
            var xy = YAHOO.util.Dom.getXY(this.contentEl);
            
            // hide/reset stuff if no scroller is needed (anymore)
            if (this.contentEl.scrollHeight <= this.contentEl.offsetHeight) {
                this.contentEl.style.width = '';
                this._scrollerEl.style.display = 'none';
                return;
            }
            
            // show all elements
            this._scrollerEl.style.display = '';
            this._c2El.style.visibility = '';
            
            // update box container height (with 2 icons of 16px)
            this._c2El.style.height = (this.contentEl.offsetHeight - 32) + 'px';
            
            // align right: scrollbar right of the text div
            if (this._config.align == 'right') {
            
                // make target div smaller so we can position scroller next to it
                this.contentEl.style.width = (this.contentEl.offsetWidth - 16 - this._config.spacing) + 'px';
                
                // position scroll container next to text
                xy[0] += this.contentEl.offsetWidth + this._config.spacing;
                YAHOO.util.Dom.setXY(this._scrollerEl, xy);
                
            }
            
            // align middle
            else 
                if (this._config.align == 'middle') {
                    xy[0] += parseInt((this.contentEl.offsetWidth / 2) + this._config.spacing - 8, 10);
                    YAHOO.util.Dom.setXY(this._scrollerEl, xy);
                    this._c2El.style.visibility = 'hidden';
                    this._c2El.style.height = (parseInt(this._c2El.offsetHeight, 10) + (32 + 8)) + 'px';
                    this._scrollerEl.style.top = (parseInt(this._scrollerEl.style.top.replace('px', ''), 10) - (16 + 4)) + 'px'
                }
                
                else {
                    throw new Error('invalid align: ' + this._config.align);
                }
            
            
            this._updateBox();
        },
        
        // re-positions the box according to the current scrollTop and scrollHeight
        _updateBox: function(){
        
            // box height represents the total height in the scrollbar		
            var h = Math.floor(this.contentEl.offsetHeight / parseInt(this.contentEl.scrollHeight) * parseInt(this._c2El.offsetHeight));
            
            this._boxEl.style.height = h + 'px';
            
            this._boxEl.style.top = (this.contentEl.scrollTop / this.contentEl.scrollHeight) * this._c2El.offsetHeight + 'px';
            
        }
        
    };
    
})();

