// Copyright 2008 Ferrari Color
// Requires jQuery
// Props to Panic for the functional inspiration http://panic.com/coda

/// <reference path="jquery.intellisense.js" />

var FC = window.FC || {};

// A horizontal scrolling pager
// Assumptions:
//    -The first div in the scroll window is the page ribbon
//    -Each child div of the page ribbon is a page
//    -The only <ul> in the page controls div is for the list of page icons
//    -The left and right buttons are divs contained in the page controls div and assigned classes of left and right respectively
//    -The left and right buttons contain an <a>, and in that <a> any text or graphics to represent the clickable portion of the button
//
// params:
//    _config.ScrollWindow, a css selector to the bounding div for the page ribbon
//    _config.PageControls, a css selector to the bounding div for paging controls
//    _config.PageWidth, the width in pixels of each page
//    _config.PageMargin, the uniform margin applied to each page
FC.ScrollPager = function(config) {

    var _config = {
        ScrollWindow: config.ScrollWindow || "div.scroll-window",
        PageWidth: config.PageWidth || 600,
        PageMargin: config.PageMargin || 20,
        PageControls: config.PageControls || "div.page-controls",

        IconWindow: config.ControlIconsWindow || (config.PageControls || "div.page-controls") + ">div.icon-window",
        IconWidth: config.IconWidth || 20
    };

    // Private Variable/Consts
    var that = this;
    var _iconRibbon = _config.IconWindow + ">ul";
    var _iconRibbonZero = $(_iconRibbon).position().left;
    var _firstVisibleIcon = 0;
    var _lastVisibleIcon = 0;
    var _visibleIconCount = 0;
    var _iconCenter = 0;
    var _iconMaxClamp = 0;
    var _pageIconsASelector = _config.PageControls + " ul>li>a";
    var _selectedClass = "selected";
    var _currentPage = 0;
    var _pageRibbon = _config.ScrollWindow + ">div:first";
    var _pageCount = $(_pageRibbon + ">div").length;
    var _pageOuterWidth = 0;
    var _pageLoaded = [];


    // This can be overridden to set the contents of the page icon
    // This will be called as each page icon is generated passing the page number
    // Any return value will be placed in the <a> of the page icon <li>
    this.GetPageIcon = function(pagen) {
        return pagen + 1;
    };

    // Replace this function to be notified when we are about to scroll to a page
    // firstTime will be true the first time this function is called for a page
    // This is useful for delaying the load of the all or part of a page's content until it is about to be shown
    this.PageChanging = function(pagen, firstTime) {

    }

    var OnPageChanging = function(pagen) {
        var first = true;
        if (_pageLoaded[pagen])
            first = false;

        if (that.PageChanging)
            that.PageChanging(pagen, first);

        _pageLoaded[pagen] = true;
    }

    // Call this after setting up the object
    this.init = function() {

        // Set the page width
        this.PageWidth(_config.PageWidth);

        // If there are no <li>'s create an <li> in the <ul> for each page
        if ($(_iconRibbon + " li").length == 0)
            this.GeneratePageIcons();

        // Execute the layout
        this.DoLayout();

        // Setup page icon click handlers
        i = 0;
        $(_pageIconsASelector).each(function() { var pagen = i++; $(this).click(function(e) { e.preventDefault(); that.ScrollToPage(pagen); }); });

        // Setup prev and next click handlers and "button" class
        $(_config.PageControls + ">div.left," + _config.PageControls + ">div.right").addClass("button");
        $(_config.PageControls + ">div.left>a").click(function(e) { e.preventDefault(); that.Scroll('left'); });
        $(_config.PageControls + ">div.right>a").click(function(e) { e.preventDefault(); that.Scroll('right'); });

        // Set current selected page
        $(_pageIconsASelector + ":eq(" + _currentPage + ")").addClass(_selectedClass);

        // Call the page change event for the first page
        OnPageChanging(_currentPage);

    };

    this.DoLayout = function() {
        // Set the width of the scroll window
        $(_config.ScrollWindow)
            .width(_pageOuterWidth)
            .css("overflow", "hidden")
            .css("position", "relative");  //fix for IE overflow problem

        // Set the width of the pages
        $(_config.PageControls).width(_pageOuterWidth);

        // Set the width of the ribbon of pages
        $(_pageRibbon)
            .width(_pageCount * _pageOuterWidth)
            .css("position", "relative");
        $(_pageRibbon + ">div")
            .width(_config.PageWidth).addClass("page")
            .css("float", "left")
            .css("margin", _config.PageMargin + "px");

        // Set the width of the icon ribbon
        var numIcons = $(_iconRibbon + " li").length;
        var iconRibbonWidth = numIcons * _config.IconWidth;
        $(_iconRibbon)
            .width(iconRibbonWidth)
            .css("position", "relative");

        var availableWidth = $(_config.IconWindow).width() - $(_config.PageControls + ">div.left>a").outerWidth() - $(_config.PageControls + ">div.right>a").outerWidth();
        var setWidth = availableWidth - (availableWidth % _config.IconWidth);
        _lastVisibleIcon = _visibleIconCount = (setWidth / _config.IconWidth);
        _iconCenter = setWidth / 2;
        _iconMaxClamp = (iconRibbonWidth < setWidth) ? 0 : iconRibbonWidth - setWidth;
        $(_config.IconWindow)
            .width(setWidth)
            .css("overflow", "hidden")
            .css("position", "relative");  //fix for IE overflow problem
    };

    // Get/Set the width of the pages
    // If the object was already init'd, call DoLayout
    this.PageWidth = function(newWidth) {
        if (newWidth) {
            _config.PageWidth = newWidth;
            _pageOuterWidth = _config.PageWidth + (_config.PageMargin * 2);
        }

        return _config.PageWidth;
    };

    // Sets the margin on the page
    // If the object was already init'd, call DoLayout
    this.PageMargin = function(newMargin) {
        if (newMargin) {
            _config.PageMargin = newMargin;
        }

        return _config.PageMargin;
    };

    // This generates/regenerates the paging icons
    // You probably want to call this if setting GetPageIcon to a custom function after calling init
    this.GeneratePageIcons = function() {
        i = 0;
        $(_iconRibbon).empty();
        $(_pageRibbon + ">div").each(function() { $(_iconRibbon).append("<li><a href=\"#page-" + i + "\">" + that.GetPageIcon(i) + "</a></li>"); i++; });
    };

    // Get/Set the class applied to the currently selected page's icon
    this.SelectedClass = function(newClass) {
        if (newClass) {
            // If any page icon has the selected class already swap it out for the new one
            $(_pageIconsASelector + " ." + _selectedClass).addClass(newClass).removeClass(_selectedClass);
            _selectedClass = newClass;
        }

        return _selectedClass;
    };

    // Scroll by one page 'left' or 'right'
    this.Scroll = function(direction) {
        // calculate the next page to scroll to, wrap if we get to the begining or end
        var nextPage = _currentPage;
        if (direction == 'right') {
            nextPage++;
            _lastVisibleIcon++;
            _firstVisibleIcon++;
            if (nextPage >= _pageCount) {
                nextPage = 0;
                _firstVisibleIcon = 0;
                _lastVisibleIcon = _visibleIconCount;
            }
        } else {
            nextPage--;
            if (nextPage < 0) {
                _lastVisibleIcon = nextPage = _pageCount - 1;
                _firstVisibleIcon = _lastVisibleIcon - _visibleIconCount;
            }
        }

        this.ScrollToPage(nextPage);
    };

    // Scroll from the current page to the specified page
    this.ScrollToPage = function(pagen) {
        // If we are already on the page, short circuit out of here
        if (pagen == _currentPage)
            return;

        // Remove the "selected" class from the previously current page and apply it to the new current page
        $(_pageIconsASelector).eq(_currentPage).removeClass(_selectedClass);
        var selectedIcon = $(_pageIconsASelector).eq(pagen).addClass(_selectedClass);

        // Call the notification event
        OnPageChanging(pagen);

        // Center the Selected paging icon
        var iconLeft = (pagen - 1) * _config.IconWidth;
        iconLeft = iconLeft - (iconLeft % _config.IconWidth);
        iconLeft = (iconLeft > _iconMaxClamp) ? _iconMaxClamp : ((iconLeft < 0) ? 0 : iconLeft); // Clamp to the max and min scroll position
        $(_iconRibbon).stop().animate({ left: -(iconLeft) }, 250);

        // Jump directly to the new page, no fancy animations
        //		$(scrollWindow + " #pages").css("left", (-_pageOuterWidth * pagen) + 'px')

        // Scale the animation time down based on the number of pages we are jumping
        var animTime = 500 * Math.cos((Math.abs(pagen - _currentPage) / _pageCount));

        // Start the scroll animation
        $(_pageRibbon).stop().animate({ left: (-_pageOuterWidth * pagen) + 'px' }, animTime);

        // Record our new current page
        _currentPage = pagen;
    };
};

if (typeof (Sys) !== "undefined") Sys.Application.notifyScriptLoaded();