
////////////////////////////////////////////////////////////////////////////////////////////////////\
// Page constructor
////////////////////////////////////////////////////////////////////////////////////////////////////
function Page(iId, iLoaded)
{
    var page = this;
    
    this.id = iId;
    this._super = Widget;
    this._super(iId);  
        
    this.onLoad = new EventHandler();
    this.loaded = iLoaded;
    
    
    this.load = function(iUrl)
        {
            if (page.loaded)
                return;
            
            var loader = new Loader(page, iUrl, this.onLoad);
            page.loaded = true;
            loader.load(iUrl);
        }
    
}


////////////////////////////////////////////////////////////////////////////////////////////////////
// PageLoader
////////////////////////////////////////////////////////////////////////////////////////////////////
function PageManager(iUrl, iPageHolder, iLoading)
{
    var pageManager = this;
    
    this.pageHolder = iPageHolder;
    this.loading = iLoading;
    
    this.pages = new Array();
    this.pageIndex = -1;
    this.pageSize = 1;
    this.itemCount = 0;
    this.itemOffset = 1;
    this.url = iUrl;

    this.onPageChanged = new EventHandler();

    
    this.init = function(iPageSize, iItemCount)
        {
            pageManager.pageSize = iPageSize;
            pageManager.itemCount = iItemCount;        
        }

    this.isPageAvailable = function(iIndex)
        {
            if (iIndex == 1 && pageManager.itemCount == 0)
                return true;
            else
            {
                var itemIndex = (iIndex-1) * pageManager.pageSize;
                return (itemIndex >= 0 && itemIndex < pageManager.itemCount);
            }
        }
    
    this.initPage = function(iIndex)
        {
            var id = pageManager.pageHolder.widgetId + '-' + iIndex;
            var page = Widget.get(id);
            
            if (!page)
            {
                if (!document.getElementById(id))
                {
                    var div = document.createElement('div');
                    div.id = id;
                    div.style.display = 'none';
                    if (pageManager.loading)
                        div.innerHTML = pageManager.loading.getElement().innerHTML;
                    pageManager.pageHolder.getElement().appendChild(div);
                }
                page = new Page(id);             
            }

            pageManager.pages[iIndex] = page;
            
            return page;
        }

    this.getPage = function(iIndex)
        {
            var page = pageManager.pages[iIndex];
            
            if (isUndefined(page))
                page = pageManager.initPage(iIndex);
            
            return page;
        }

    this.showPage = function(iIndex)
        {
            if (pageManager.isPageAvailable(iIndex))
            {
                var page = pageManager.getPage(iIndex);

                // load if not yet loaded
                if (!page.loaded)
                    page.load(addUrlParam(pageManager.url, 'start', (iIndex-1) * pageManager.pageSize + pageManager.itemOffset));

                // hide current page
                if (pageManager.pageIndex >= 0)
                    pageManager.pages[pageManager.pageIndex].hide();

                // show selected page
                pageManager.pageIndex = iIndex;
                page.show();
                
                // invoke event
                pageManager.onPageChanged.invoke();
            }
        }
    
    this.update = function()
        {
            pageManager.onPageChanged.invoke();
        }
}


////////////////////////////////////////////////////////////////////////////////////////////////////
// PageController constructor
////////////////////////////////////////////////////////////////////////////////////////////////////
function PageController(iId, iPageManager)
{
    var pageController = this;
    
    this.id = iId;
    this._super = Widget;
    this._super(iId);    
    
    this.controls = new Widget(iId);
    this.previous = new Button(iId + '-previous');
    this.next = new Button(iId + '-next');
    this.pageList = new Widget(iId + '-list');
    this.pageManager = iPageManager;


    function moveToPageEventGenerator(iPage)
    { return function() { pageController.moveToPage(iPage); } }



    this.moveToPage = function(iPage)
        {
            pageController.pageManager.showPage(iPage);
            pageController.update();
        }
            
    this.moveToPrevious = function()
        {
            pageController.moveToPage(pageController.pageManager.pageIndex - 1);
        }
        
    this.moveToNext = function()
        {
            pageController.moveToPage(pageController.pageManager.pageIndex + 1);
        }

    this.update = function()
        {
            var pageListElement = pageController.pageList.getElement();
            var pageCount = 0;
            
            while (pageListElement.hasChildNodes())
                pageListElement.removeChild(pageListElement.firstChild);

            if (pageController.pageManager.pageSize > 0)
                pageCount = pageController.pageManager.itemCount / pageController.pageManager.pageSize;
            
            if (pageCount > 1)
            {
                var pageIndex = pageController.pageManager.pageIndex;
                var target = pageIndex;
                var last = 0;
                
                // previous, next buttons
                if (pageController.pageManager.isPageAvailable(pageIndex - 1))
                    pageController.previous.show();
                else
                    pageController.previous.hide();
                
                if (pageController.pageManager.isPageAvailable(pageIndex + 1))
                    pageController.next.show();
                else
                    pageController.next.hide();               
                
                // recreate list
                if (target < 3)
                    target = 3;
                else if (target > pageCount - 2)
                    target = pageCount - 2;
                
                for (var i = 1; pageController.pageManager.isPageAvailable(i); i++)
                {
                    if (i == 1 || ((i >= target - 2) && (i <= target + 2)) || i >= pageCount)
                    {
                        if (i > last + 1)
                            pageListElement.appendChild(document.createTextNode(' ... '));
                        else if (i > 1)
                            pageListElement.appendChild(document.createTextNode(' - '));
                        
                        if (i == pageIndex)
                            pageListElement.appendChild(document.createTextNode(i));
                        else
                        {
                            var node = document.createElement('span');
                            node.appendChild(document.createTextNode(i));
                            node.onclick = moveToPageEventGenerator(i);
                            pageListElement.appendChild(node);
                        }

                        last = i;
                    }
                }
                
                pageController.show();
            }
            else
                pageController.hide();
        }


    this.previous.onClick.add(this.moveToPrevious);
    this.next.onClick.add(this.moveToNext);
    this.pageManager.onPageChanged.add(this.update);
    
}