/*
    This custom scrollbar is used in the following pages:
    /365-Cellular-Elixirs/*.aspx
    /FAQ.aspx
    
*/

YAHOO.namespace("nurun");
/**
 * @param {String|HTMLElement} contentId  The element whose conents need a scrollbar
 * @requires YAHOO.util.Dom, YAHOO.util.Event, YAHOO.util.Anim (Optional)
 * @todo: - minimum thumb size
 *        - onresize event to recalc scrollbar/content positions
 *        - detect new content to recalc thumb size
 */
YAHOO.nurun.VertScrollbar = function (contentId, userConfig) {
    // Local variables
    var Y = YAHOO.util.Dom,
        cfgKey,
        contentHeight,
        wrapperHeight,
        scrollBgHeight,
        thumbHeight,
        ratio,
        contentEl,
        scrollBgWidth,
        thumbHd,
        thumbBd,
        thumbFt,
        thumbBdHeight,
        childrenHeight = 0,
        i;
    
    // Default config values
    this.cfg = {
        scrollBgWidth: 20,
        scrollRatio: .1,
        autoScroll: true,
        startAutoScrollTimeout: 250,
        scrollInterval: 100
    };
    
    // Overwrite default config values
    for (cfgKey in userConfig) {
        if (userConfig.hasOwnProperty(cfgKey)) {
            this.cfg[cfgKey] = userConfig[cfgKey];
        }
    }
    
    function isHidden(el) {
        if (YAHOO.util.Dom.getStyle(el, "visibility") === "hidden") {
            return true;
        } else {
            return false;
        }
    };
    function isDisplayNone(el) {
        if (YAHOO.util.Dom.getStyle(el, "display") === "none") {
            return true;
        } else {
            return false;
        }
    };
    
    this.contentEl = Y.get(contentId);
    
    if (this.contentEl && this.contentEl.scrollHeight > this.contentEl.offsetHeight) {
    	
        this.wrapperEl = document.createElement("div");
        this.scrollbarEl = document.createElement("div");
        this.scrollUpEl = document.createElement("div");
        this.scrollDownEl = document.createElement("div");
        this.scrollBgEl = document.createElement("div");
        this.thumbEl = document.createElement("div");
        thumbHd = document.createElement("div");
        thumbBd = document.createElement("div");
        thumbFt = document.createElement("div");
        this.intervalId = null;
        this.timeoutId = null;
        
        // Nest elements and append to DOM (causes reflow but also returns reliable dimension values)
        Y.insertBefore(this.wrapperEl, this.contentEl);
        this.wrapperEl.appendChild(this.contentEl);
        this.wrapperEl.appendChild(this.scrollbarEl);
        this.scrollbarEl.appendChild(this.scrollUpEl);
        this.scrollbarEl.appendChild(this.scrollBgEl);
        this.scrollbarEl.appendChild(this.scrollDownEl);
        this.scrollBgEl.appendChild(this.thumbEl);
        this.thumbEl.appendChild(thumbHd);
        this.thumbEl.appendChild(thumbBd);
        this.thumbEl.appendChild(thumbFt);
        
        contentHeight = parseInt(Y.getStyle(this.contentEl, "height"), 10);
        if (isNaN(contentHeight)) {
            //throw new Error("YAHOO.nurun.Scrollbars: no height set on content element");
            return false
        }
        
        // Content wrapper element
        this.wrapperEl.id = "_" + this.contentEl.id;
        this.wrapperEl.className = "wrapper scroll";
        this.wrapperEl.style.height = contentHeight + "px";
        this.wrapperEl.style.overflow = "hidden";
        this.wrapperEl.style.position = "relative";
        wrapperHeight = this.wrapperEl.offsetHeight;
        
        // Content element
        YAHOO.util.Dom.addClass(this.contentEl, "scrolled");
        this.contentEl.style.height = "auto";
        this.contentEl.style.position = "absolute";
        this.contentEl.style.top = "0";
        this.contentEl.style.left = "0";
        this.contentEl.style.overflow = "hidden"; // patch for Firefox as it has trouble redrawing overflowed div (bleeds outside the wrapper)
        contentHeight = this.contentEl.offsetHeight;
        
        // Scrollbar wrapper element
        this.scrollbarEl.id = this.contentEl.id + "-scrollbar";
        this.scrollbarEl.className = "scrollbar";
        this.scrollbarEl.style.position = "absolute";
        this.scrollbarEl.style.top = "0";
        
        // Background element
        this.scrollBgEl.id = this.contentEl.id + "-sBg";
        this.scrollBgEl.className = "scrollbar-background";
        this.scrollBgEl.style.position = "relative";
        scrollBgWidth = this.scrollBgEl.offsetWidth;
        if (scrollBgWidth === 0 || scrollBgWidth === document.body.offsetWidth) { // the latter check is for Safari
            scrollBgWidth = this.cfg.scrollBgWidth; // assign to this variable for reuse with up/down buttons
            this.scrollBgEl.style.width = scrollBgWidth + "px";
        }
        
        // Up button element
        this.scrollUpEl.id = this.contentEl.id + "-up";
        this.scrollUpEl.className = "up-button";
        this.scrollUpEl.style.width = scrollBgWidth + "px";
        if (this.scrollUpEl.offsetHeight === 0) {
            this.scrollUpEl.style.height = scrollBgWidth + "px";
        }
        
        // Down button element
        this.scrollDownEl.id = this.contentEl.id + "-down";
        this.scrollDownEl.className = "down-button";
        this.scrollDownEl.style.width = scrollBgWidth + "px";
        if (this.scrollDownEl.offsetHeight === 0) {
            this.scrollDownEl.style.height = scrollBgWidth + "px";
        }
        
        // Thumb element
        this.thumbEl.id = this.contentEl.id + "-thumb";
        this.thumbEl.className = "thumb";
        thumbHd.className = "hd";
        thumbFt.className = "ft";
        thumbBd.className = "bd";
        
        
        // Set scroll position
        this.scrollbarEl.style.left = (this.contentEl.offsetWidth - scrollBgWidth) + "px";
        this.scrollBgEl.style.height = (wrapperHeight - this.scrollUpEl.offsetHeight - this.scrollDownEl.offsetHeight) + "px";
        scrollBgHeight = this.scrollBgEl.offsetHeight;

        
        // Set content and wrapper widths relative to scroll width and update local variable values
        this.contentEl.style.width = (this.contentEl.offsetWidth - scrollBgWidth) + "px";
        contentHeight = this.contentEl.offsetHeight;
        this.wrapperEl.style.width = (this.contentEl.offsetWidth + this.scrollBgEl.offsetWidth) + "px";
        wrapperHeight = this.wrapperEl.offsetHeight;
        
        // Create slider object for use as scrollbar
        ratio = scrollBgHeight / contentHeight;
        contentEl = this.contentEl; // local var bound to anonymous event funcitons through closure
        thumbHeight = Math.floor(wrapperHeight * ratio);
        this.thumbEl.style.height = thumbHeight + "px";
        thumbBdHeight = thumbHeight - thumbHd.offsetHeight - thumbFt.offsetHeight;
        thumbBdHeight = thumbBdHeight < 0 ? 0 : thumbBdHeight;
        thumbBd.style.height = thumbBdHeight + "px";
        
        /** 
         * Find out if the scrollbar element is "hidden" or "display none" due to an ancestor
         * find the ancestor, unhide it, instantiate the scrollbar and rehide it.
         */
        /*
        if (isHidden(this.scrollbarEl) || isDisplayNone(this.scrollbarEl)) {
            var hiddenEl = YAHOO.util.Dom.getAncestorBy(this.scrollbarEl, function (el) {
                if (isHidden(el) || isDisplayNone(el)) {
                    return true;
                }
                return false;
            });
            var resetType;
            if (isHidden(hiddenEl)) {
                resetType = "visibility";
                YAHOO.util.Dom.setStyle(hiddenEl, "visibility", "visible");
            } else if (isDisplayNone(hiddenEl)) {
                resetType = "display";
                YAHOO.util.Dom.setStyle(hiddenEl, "display", "");
            }
            this.slider = YAHOO.widget.Slider.getVertSlider(this.scrollBgEl, this.thumbEl, 0, (scrollBgHeight - thumbHeight));
            switch (resetType) {
            case "visibility":
                YAHOO.util.Dom.setStyle(hiddenEl, "visibility", "hidden");
                break;
            case "display":
                YAHOO.util.Dom.setStyle(hiddenEl, "display", "none");
                break;
            }
        } else {
            this.slider = YAHOO.widget.Slider.getVertSlider(this.scrollBgEl, this.thumbEl, 0, (scrollBgHeight - thumbHeight));
        }
        */
        this.slider = YAHOO.widget.Slider.getVertSlider(this.scrollBgEl, this.thumbEl, 0, (scrollBgHeight - thumbHeight));
        this.slider.animate = false;
        this.slider.subscribe("change", function (offset) {
            contentEl.style.top = Math.floor(0 - (offset / ratio)) + "px";
        });
        
        function doScroll(slider, dir) {
            var val = slider.getValue();
            slider.setValue(val + (thumbHeight * dir));
        };
        
        // Wire up button to animation
        this.scrollUpEl.onmousedown = function (that) {
            return function () {
                doScroll(that.slider, -1);
                if (that.cfg.autoScroll) {
                    that.timeoutId = window.setTimeout(function () {
                        that.intervalId = window.setInterval(function () {
                            doScroll(that.slider, -1);
                        }, that.cfg.scrollInterval)
                    }, that.cfg.startAutoScrollTimeout);
                }
            }
        }(this);
        
        this.scrollUpEl.onmouseup = function (that) {
            return function () {
                window.clearTimeout(that.timeoutId);
                window.clearInterval(that.intervalId);
            }
        }(this);
        
        // Wire down button to animation
        this.scrollDownEl.onmousedown = function (that) {
            return function () {
                doScroll(that.slider, 1);
                if (that.cfg.autoScroll) {
                    that.timeoutId = window.setTimeout(function () {
                        that.intervalId = window.setInterval(function () {
                            doScroll(that.slider, 1);
                        }, that.cfg.scrollInterval)
                    }, that.cfg.startAutoScrollTimeout);
                }
            };
        }(this);
        
        this.scrollDownEl.onmouseup = function (that) {
            return function () {
                window.clearTimeout(that.timeoutId);
                window.clearInterval(that.intervalId);
            };
        }(this);
        
        // Wire up/down arrow keys
        /*
        this.arrows = new YAHOO.util.KeyListener(document, {keys: [38, 40]}, 
            {
                fn: function (eType, codeAndEv)  {
                    console.log("key");
                    if (codeAndEv[0] === 38) { // up
                        this.scrollUpEl.onmousedown.apply(this);
                        this.scrollUpEl.onmouseup.apply(this);
                    } else if (codeAndEv[0] === 40) { // down
                        this.scrollDownEl.onmousedown.apply(this);
                        this.scrollDownEl.onmouseup.apply(this);
                    }
                }, scope: this, correctScope: true
            });
        this.arrows.enable();
        */
        
        // assign/remove class names per mouse states using event delegation
        this.scrollbarEl.onmouseover = function (e) {
            e = e || event;
            target = e.target || e.srcElement;
            Y.addClass(target, "over");
        };
        this.scrollbarEl.onmouseout = function (e) {
            e = e || event;
            target = e.target || e.srcElement;
            Y.removeClass(target, "over");
        };
        this.scrollbarEl.onmousedown = function (e) {
            e = e || event;
            target = e.target || e.srcElement;
            Y.addClass(target, "down");
        };
        this.scrollbarEl.onmouseup = function (e) {
            e = e || event;
            target = e.target || e.srcElement;
            Y.removeClass(target, "down");
        };
    } else {
        //throw new Error("YAHOO.nurun.Scrollbars: Invalid contentId or HTMLElement reference");
        return false;
    }
};
