

//
// PageList is a scrollable list of pages
//
Jaman.PageList = function(id, width, height, totalPages)
{
	this._id = id;
	this._width = width;
	this._height = height;
	this._totalPages = totalPages;
	
	this._dom = null;
	this._leftScrollbar = null;
	this._rightScrollbar = null;
	this._scrollingDiv = null;
	this._scrollingRow = null;
	
	this._currentPage = 0;
	this._fetchNextPageHandler = null;
	this._loadNextPageHandler = null;
	this._handlerCalled = false;
	this._isScrolling = false;
}

Jaman.PageList.prototype.setHandlers = function(fetchNextPageHandler, loadNextPageHandler)
{
    this._fetchNextPageHandler = fetchNextPageHandler;
	this._loadNextPageHandler = loadNextPageHandler;
}

Jaman.PageList.prototype.setTotalPages = function(totalPages)
{
    this._totalPages = totalPages;
}

Jaman.PageList.prototype.show = function()
{
    this.getDOM();
    
    if (this._dom)
    {
    	this._dom.style.display = "block";
    }
}

Jaman.PageList.prototype.hide = function()
{
	this.getDOM();
	
	if (this._dom)
	{
		this._dom.style.display = "none";
	}
}

Jaman.PageList.prototype.getDOM = function()
{
	if (!this._dom)
	{
	   this.createDOM();
	}
	
	return this._dom;
}

Jaman.PageList.prototype.createDOM = function()
{
	if (!this._dom)
	{
		this._leftScrollbar = new Jaman.PageList.Scrollbar(true, this);
		this._rightScrollbar = new Jaman.PageList.Scrollbar(false, this);
		
		this._scrollingRow = TR(null);
		
		this._scrollingDiv = 
		  DIV({"style": "overflow: hidden; " + 
		      "position: relative; " +
		      "height: " + this._height + "px; " + 
			  "width: " + this._width + "px;" },
			  TABLE(null,
			     TBODY(null,
				    this._scrollingRow)));
		
		this._dom = TABLE(null,
		  TBODY(null, 
			  TR(null,
			      this._leftScrollbar.getDOM(),
				  TD(null, this._scrollingDiv),
				  this._rightScrollbar.getDOM())));
			  
	    // append to element specified by this._id
	    if (this._id)
		{
			var elem = $(this._id);
			if (elem)
			{
				elem.appendChild(this._dom);				
		    }
		}
	}
}

Jaman.PageList.prototype.addPage = function(element)
{
	// make sure we create dom first
	this.createDOM();
	
	var isFirstPage = (this._scrollingRow.childNodes.length == 0);
	this._scrollingRow.appendChild(TD(null, element));
	
	this.resetScrollbars();
}

Jaman.PageList.prototype.scrollToStart = function()
{
    // make sure we create dom first
    this.createDOM();
    
    this._scrollingDiv.scrollLeft = 0;
    this._currentPage = 0;	
}

Jaman.PageList.prototype.getPageCount = function()
{
	// make sure we create dom first
    this.createDOM();
    
	return this._scrollingRow.childNodes.length;
}

Jaman.PageList.prototype.removePages = function()
{
	// make sure we create dom first
    this.createDOM();
	
	// reset scrollingRow dom
	var length = this._scrollingRow.childNodes.length;
	for (var i = length - 1; i >= 0 ; i--)
	{
	   MochiKit.DOM.removeElement(this._scrollingRow.childNodes[i]);	
	}
	
	this._scrollingDiv.style.width = this._width + "px";
	this._scrollingDiv.style.height = this._height + "px";
	this.resetScrollbars();
	this._currentPage = 0;
}

Jaman.PageList.prototype.resetScrollbars = function() 
{
    if (this._isScrolling || this._currentPage == 0) 
	{
        this._leftScrollbar.disable();
    } 
	else 
	{
        this._leftScrollbar.enable();
    }
	
	if (!this._isScrolling && this._currentPage < this.getPageCount() - 1) 
	{
        this._rightScrollbar.enable();
    } 
	else 
	{
        this._rightScrollbar.disable();
    }
}

Jaman.PageList.prototype.callFetchNextPageHandler = function()
{
    this._isScrolling = false;
    
	var loadedPages = this.getPageCount();
	    
    if (this._fetchNextPageHandler && typeof(this._fetchNextPageHandler) == "function" && 
        this._currentPage == loadedPages - 1 && loadedPages < this._totalPages)
    {
        // call it asynchronously
        MochiKit.Async.callLater(0.05, this._fetchNextPageHandler, this._currentPage);
    }
}

Jaman.PageList.prototype.callLoadNextPageHandler = function()
{
    this._isScrolling = false;
    
    if (!this._handlerCalled)
    {
        var loadedPages = this.getPageCount();
        
        if (this._loadNextPageHandler && typeof(this._loadNextPageHandler) == "function" && 
            this._currentPage == loadedPages - 1 && loadedPages < this._totalPages)
        {
            // call it asynchronously
            MochiKit.Async.callLater(0.05, this._loadNextPageHandler, this._currentPage);
        }
        
        this._handlerCalled = true;
    }
}

Jaman.PageList.prototype.startScroll = function(isLeft) 
{
	this._handlerCalled = false;
	
	var newPage = isLeft ? this._currentPage - 1 : this._currentPage + 1;
	newPage = Math.max(0, Math.min(newPage, this.getPageCount() - 1));
	
	var newDelta = this._scrollingRow.childNodes[newPage].offsetWidth; // do not use this._width as page can be a table and it might be wider.
	
	// scroll to the end
	if (newDelta < this._width)
	{
	    newDelta = this._width;
	}
	
	var currentObj = this;
	MochiKit.Visual.scroll(this._scrollingDiv,
	   {delta: (isLeft ? -1 * newDelta : newDelta),
	    //transition: MochiKit.Visual.Transitions.linear,
	    duration: 1.5,
	    afterFinishInternal: function (effect) {
	    	currentObj.callLoadNextPageHandler();
	    	currentObj.resetScrollbars();
        }});
	
    if (isLeft) 
	{
        this._currentPage--;
        if (this._currentPage < 0) 
		{
            this._currentPage = 0;
        }
    } 
	else 
	{
        this._currentPage++;
        if (this._currentPage == this._scrollingRow.childNodes.length) 
		{
            this._currentPage = this._scrollingRow.childNodes.length;
        }
    }
    
    this._isScrolling = true;
    this.resetScrollbars();
    
    this.callFetchNextPageHandler();
}

// ****** PageList Scrollbar ******
Jaman.PageList.Scrollbar = function(isLeft, par) 
{
    this.isLeft = isLeft;
    this.parentGrid = par;
    // internal variables.
    this.dom = null;
    this.imgDOM = null;
    this.isEnabled = false;
}

Jaman.PageList.Scrollbar.prototype.destroy = function() 
{
    if (this.dom) 
	{
        Jaman.destroyObject(this.imgDOM);
        Jaman.destroyObject(this.dom);
    }
    this.dom = null;
    this.imgDOM = null;
}

Jaman.PageList.Scrollbar.prototype.enable = function() 
{
    if (this.isEnabled) return;

    this.isEnabled = true;
    this.imgDOM.style.cursor = "hand";
    this.imgDOM.style.cursor = "pointer";
    Jaman.setPNGSrc(this.imgDOM, "/scroll_images/sidescroll_arrow_" + (this.isLeft ? "left" : "right") + "-on.png");
}

Jaman.PageList.Scrollbar.prototype.disable = function() 
{
    if (!this.isEnabled) return;

    this.isEnabled = false;
    this.imgDOM.style.cursor = "default";
    Jaman.setPNGSrc(this.imgDOM, "/scroll_images/sidescroll_arrow_" + (this.isLeft ? "left" : "right") + "-off.png");
}

Jaman.PageList.Scrollbar.prototype.getDOM = function() 
{
    if (this.dom) 
	{
        return this.dom;
    }

    var currentObj = this;

    this.imgDOM = Jaman.imagePNG("/scroll_images/sidescroll_arrow_" + (this.isLeft ? "left" : "right") + (this.isEnabled ? "-on" : "-off") + ".png", 16, 16, "spacer");
    this.dom = TD(null, this.imgDOM);
    this.dom.style.padding = "10px";
    if (this.isLeft) 
	{
        this.dom.style.paddingLeft = "5px";
    } 
	else 
	{
        this.dom.style.paddingRight = "5px";
    }

    this.imgDOM["onmouseover"] = function() { currentObj.onMouseOver(); };
    this.imgDOM["onmouseout"] = function() { currentObj.onMouseOut(); };
    this.imgDOM["onclick"] = function() { currentObj.onMouseDown(); };

    return this.dom;
}

Jaman.PageList.Scrollbar.prototype.onMouseDown = function() 
{
    if (!this.isEnabled) return;

    Jaman.setPNGSrc(this.imgDOM, "/scroll_images/sidescroll_arrow_" + (this.isLeft ? "left" : "right") + "-over.png");
    this.parentGrid.startScroll(this.isLeft);
}

Jaman.PageList.Scrollbar.prototype.onMouseOver = function() 
{
    if (!this.isEnabled) return;

    Jaman.setPNGSrc(this.imgDOM, "/scroll_images/sidescroll_arrow_" + (this.isLeft ? "left" : "right") + "-over.png");
}

Jaman.PageList.Scrollbar.prototype.onMouseOut = function() 
{
    if (!this.isEnabled) return;

    Jaman.setPNGSrc(this.imgDOM, "/scroll_images/sidescroll_arrow_" + (this.isLeft ? "left" : "right") + "-on.png");
}

/***********************************************************************************************
//
//  PageListLib
//
***********************************************************************************************/
PageListLib = {};

// always show only 4 pages
PageListLib.MAX_NUMBER_OF_PAGES = 4;

// constants apply to movie finder grid, overridden for user finder grid!
PageListLib.GRID_WIDTH = 550; // add 5 pixels buffer
PageListLib.GRID_HEIGHT = 260;
PageListLib.PAGE_SIZE = 8;

PageListLib.numberOfItems = null;
PageListLib.makeInitialPagesRequest = null;
PageListLib.initialRequestOkay = null;
PageListLib.makeNextPageRequest = null;
PageListLib.nextPageResponse = null;
PageListLib.currentCall = null;
    
PageListLib.getTotalItems = function()
{
	return Math.min(PageListLib.numberOfItems, PageListLib.MAX_NUMBER_OF_PAGES * PageListLib.PAGE_SIZE);
}
PageListLib.getTotalPages = function()
{
	
	return Math.floor(PageListLib.getTotalItems() / PageListLib.PAGE_SIZE) + 1;
}

PageListLib.loadInitialPages = function() 
{
    if ($("displayPage0"))
    {
        PageListLib.pageList.addPage($("displayPage0"));
    }
    
    if ($("displayPage1"))
    {
        PageListLib.pageList.addPage($("displayPage1"));
    }
    
    if ($("totalNumberDiv"))
    {
        PageListLib.numberOfItems = eval($("totalNumberDiv").innerHTML);
        PageListLib.pageList.setTotalPages(PageListLib.getTotalPages());
    }
        
    hideElement("spinnerDiv");
    showElement("pageListDiv");
    
    setTimeout( function() {
    	PageListLib.pageList.scrollToStart();  
    	PageListLib.pageList.resetScrollbars(); 
    	}, 100);
}
    
PageListLib.fetchInitialPages = function() 
{
    hideElement("generalErr");
    hideElement("pageListDiv");
    showElement("spinnerDiv");
    PageListLib.pageList.removePages();
    
    var d = PageListLib.makeInitialPagesRequest();
    PageListLib.currentCall = d;
    d.addCallbacks(function(resp) { PageListLib.fetchInitialPagesOkay(d, resp); }, function(resp) { PageListLib.fetchErr(resp); });
}
    
PageListLib.fetchInitialPagesOkay = function(deferred, resp) 
{
    if (deferred == PageListLib.currentCall)
    {
        $("stagingDiv").innerHTML = resp.responseText;
        PageListLib.loadInitialPages();
    
        if(PageListLib.initialRequestOkay != null && typeof(PageListLib.initialRequestOkay) == "function")
        {
            PageListLib.initialRequestOkay(resp);
        }
        
        // reset
        PageListLib.currentCall = null;
    }
}
    
PageListLib.fetchNextPage = function() 
{
    hideElement("generalErr");
    
    // reset
    PageListLib.nextPageResponse = null;
    
    var pageOffset = PageListLib.pageList.getPageCount() * PageListLib.PAGE_SIZE;
    var d = PageListLib.makeNextPageRequest(pageOffset);
    d.addCallbacks(function(resp) { PageListLib.fetchMoreUsersOkay(resp); }, function(resp) { PageListLib.fetchErr(resp); });
}

PageListLib.fetchMoreUsersOkay = function(resp) 
{
    // loadNextPage handler was already called, load it right now
    if (PageListLib.nextPageResponse != null)
    {
        PageListLib.nextPageResponse = resp;
        PageListLib.loadNextPage();
    }
    else
    {
        // just wait for loadNextPage to be called
        PageListLib.nextPageResponse = resp;
    }
}

PageListLib.fetchErr = function(err) 
{
    VideoLib.log("generalErr", "Sorry, can not complete your request because of the following error.<br/>" + err.faultString);
    showElement("generalErr");
    
    // reset
    PageListLib.currentCall = null;
}

PageListLib.loadNextPage = function()
{
    if (PageListLib.nextPageResponse != null)
    {
	    $("stagingDiv").innerHTML = PageListLib.nextPageResponse.responseText;
	    
	    var displayPageName = "displayPage" + PageListLib.pageList.getPageCount();
	    if ($(displayPageName))
	    {
	        PageListLib.pageList.addPage($(displayPageName));
	    }
	    
	    // reset
	    PageListLib.nextPageResponse = null;
    }
    else
    {
        PageListLib.nextPageResponse = "loadNextPage already called!";
    }
}

PageListLib.handleLoad = function() 
{
    PageListLib.pageList = new Jaman.PageList("pageListDiv", PageListLib.GRID_WIDTH, PageListLib.GRID_HEIGHT, PageListLib.getTotalPages());
    PageListLib.loadInitialPages();
    PageListLib.pageList.setHandlers(PageListLib.fetchNextPage, PageListLib.loadNextPage);
}

/** @id MochiKit.Visual.Scroll */
MochiKit.Visual.Scroll = function (element, options) {
    var cls = arguments.callee;
    if (!(this instanceof cls)) {
        return new cls(element, options);
    }
    this.__init__(element, options);
};

/** @id MochiKit.Visual.scroll */
MochiKit.Visual.scroll = function (element, /* optional */ options) {
    /***

    Scroll a given element

    @param options: ...

    ***/
    return new MochiKit.Visual.Scroll(element, options);
};


MochiKit.Visual.Scroll.prototype = new MochiKit.Visual.Base();

MochiKit.Base.update(MochiKit.Visual.Scroll.prototype, {
    /***

    Scroll an element.

    ***/

    __class__ : MochiKit.Visual.Scroll,

    __init__: function (element, /* optional */options) {
        this.element = MochiKit.DOM.getElement(element);
        options = MochiKit.Base.update({
            delta: 0
        }, options);
        this.start(options);
    },

    /** @id MochiKit.Visual.Scroll.prototype.setup */
    setup: function () {
    	this.scrollStart = this.element.scrollLeft;
        this.delta = this.options.delta;
    },

    /** @id MochiKit.Visual.Scroll.prototype.update */
    update: function (position) {
    	this.element.scrollLeft = this.scrollStart + (position * this.delta);
    }
});
