
function Pagination(viewport, url, options)
{
    this.MoreCompleted = this.__MoreCompleted.bind(this);

    this._viewport = $(viewport);
    this._url = url;
    this._params = $H().merge(options.params);

    this._lessDiv = $(document.createElement("div"));
    this._viewport.appendChild(this._lessDiv);

    this._lessCommand = $(options.lessCommand);  
    if (this._lessCommand)
    {
        this._lessMode = new CommandMode(this._lessCommand, false);
        this.BindCommand(this._lessCommand, this.LessCommandOnClick.bindAsEventListener(this));
    }  

    this._moreCommand = $(options.moreCommand);   
    if (this._moreCommand)
    {
        this._moreMode = new CommandMode(this._moreCommand, this.EnableMore());
        this.BindCommand(this._moreCommand, this.MoreCommandOnClick.bindAsEventListener(this)); 
    }
    
    this._moreLessSection = $(options.moreLessSection);
    if (this._moreLessSection && !this.EnableMore())
    {
        this._moreLessSection.setStyle({display: 'none'});
    }
};

Pagination.prototype._lessActivated = false;

Pagination.prototype.Reset = function Pagination_Reset(json)
{
    this._lessDiv = $(document.createElement("div"));
    this._viewport.appendChild(this._lessDiv);

    this._params = this._params.merge($H(json));
    
    this._lessMode.setEnabled(false);
    this._moreMode.setEnabled(this.EnableMore());

    this._lessActivated = false;
}

Pagination.prototype.BindCommand = function Pagination_BindCommand(elt, listener)
{
    if (elt.match("a"))
    {
        elt.observe('click', listener);
    }
    else 
    {
        elt.getElementsBySelector("a").each(function(link) 
            {
                link.observe('click', listener);
            });
    }
};

Pagination.prototype.EnableMore = function Pagination_EnableMore()
{
    return this._params["enableMore"] == "true";
};

Pagination.prototype.LessCommandOnClick = function Pagination_LessCommandOnClick(e)
{
    Event.stop(e);
    
    if (this._busy == true || !this._lessMode.getEnabled())
        return;
    
    this._busy = true;
    this._lessActivated = true;
    
    new Effect.ScrollTo(this._viewport, 
        {
            duration:0.3, 
            afterFinish: function()
            {
                new Effect.BlindUp(this._lessDiv, {duration:0.3});
            }.bind(this)
        });
    this._lessMode.setEnabled(false);
    this._moreMode.setEnabled(true);
    this._busy = false;    
};

Pagination.prototype.MoreCommandOnClick = function Pagination_MoreCommandOnClick(e)
{
    Event.stop(e);

    if (this._lessActivated)
    {
        this._lessActivated = false;
        new this._transition(this._lessDiv);
        this._lessMode.setEnabled(true);
        this._moreMode.setEnabled(this.EnableMore());
        return true;
    }

    if (this._busy == true || !this.EnableMore())
        return;
        
    this._busy = true;
    this._scrollDiv = $(document.createElement("div"));
    this._scrollDiv.hide();
    this._lessDiv.appendChild(this._scrollDiv);
    
    new Ajax.Updater(
        this._scrollDiv,
        this._url,
        {            
            parameters: this._params.toQueryString(),
            onComplete: this.MoreCompleted
        });
};


Pagination.prototype.__MoreCompleted = function Pagination_MoreCompleted(transport, json)
{
    this._busy = false;

    this._params = this._params.merge($H(json));
    
    this._lessMode.setEnabled(true);
    this._moreMode.setEnabled(this.EnableMore());
    
    new this._transition(this._scrollDiv);
    this._scrollDiv = null;
};

Pagination.prototype._transition = DefaultTransition;



function DefaultTransition(elt)
{
    this._elt = elt;
    new Effect.BlindDown(this._elt, {duration:0.3, afterFinish:this.scrollToMoreMember.bind(this) });
    new Effect.Highlight(this._elt, {duration:2, startcolor:"#e0edf8", endcolor:"#ffffff"});    
};

DefaultTransition.prototype.scrollToMoreMember = function()
{
    new Effect.ScrollTo(this._elt, {duration:0.3});
};



function CommandMode(elt, enabled)
{
    this._elt = elt;
    this.setEnabled(enabled);
};

CommandMode.prototype.getEnabled = function CommandMode_getEnabled()
{
    return this._enabled;
};

CommandMode.prototype.setEnabled = function CommandMode_setEnabled(enabled)
{
    this._enabled = enabled;
    if (this._enabled)
    {
        this._elt.removeClassName("disabledcommand");
    }
    else
    {
        this._elt.addClassName("disabledcommand");
    }
};



function IndexedPagination(viewport, url, params)
{
    this._viewport = $(viewport);
	this._url = url;
	this._params = params;
	this._menus = $A(this._params.pagingIds);
	this._currentPage = 1;

	var me = this;
	this._menus.each(function(menu) {
			$(menu).getElementsBySelector("a").each(function(link) {
				if (link.hasClassName("paginglink"))
					link.observe("click", me.GetPage.bindAsEventListener(me));
				else if (link.hasClassName("pagingprevious"))
					link.observe("click", me.GetPrevious.bindAsEventListener(me));
				else if (link.hasClassName("pagingnext"))
					link.observe("click", me.GetNext.bindAsEventListener(me));
			})
	});
}

IndexedPagination.prototype.GetPrevious = function IndexedPagination_GetPrevious(e)
{
    Event.stop(e);
    
    this.GetPage(this._currentPage - 1);
}

IndexedPagination.prototype.GetNext = function IndexedPagination_GetNext(e)
{
    Event.stop(e);
    
    this.GetPage(this._currentPage + 1);
}

IndexedPagination.prototype.GetPage = function IndexedPagination_GetPage(e)
{
    var requestedPage = e;
	if (typeof(e) == "object")
	{
		Event.stop(e);
		var clickedElt = Event.element(e);
		requestedPage = parseInt(clickedElt.innerHTML);
	}

	var totalPageCount = this._params.totalPageCount;
	var visiblePageCount = this._params.visiblePageCount;
	var pageSize = this._params.pageSize;
	var totalItemCount = this._params.totalItemCount;
	var order = this._params.order;

	if (requestedPage < 1 || requestedPage > totalPageCount) return;    

	var itemsIndex = (requestedPage > 0) ? ((requestedPage - 1) * pageSize) : 0;
	var itemsCount = (itemsIndex + pageSize <= totalItemCount) ? pageSize : totalItemCount - itemsIndex;
	
	if (typeof(this._params.itemsToPage) != undefined && this._params.itemsToPage != null)
	{		
		var itemsToRequest = this._params.itemsToPage.slice(itemsIndex, itemsIndex + itemsCount);
	}
	
	var updaterParams = $H({sortOrder: order, requestedPage: requestedPage, requestedItems: itemsToRequest, pageSize: pageSize }).merge(this._params.extraUpdaterParams);
	new Ajax.Updater(
		{ success: this._viewport }, this._url, 
		{
			method: 'get',
			parameters: updaterParams.toQueryString(), 
			evalScripts: true
		});

	var startIndex = Math.floor(requestedPage - (visiblePageCount / 2));
	var endIndex = Math.floor(requestedPage + (visiblePageCount / 2));
	if (startIndex < 1) startIndex = 1;
	else if (endIndex > totalPageCount) startIndex = (totalPageCount - visiblePageCount) + 1;

	this._menus.each(function(menu)
		{
			var index = startIndex;
			$(menu).getElementsBySelector("a").each(function(link)
				{
					if (link.hasClassName("paginglink"))
					{
						link.removeClassName("selected"); 
						if (visiblePageCount < totalPageCount) link.innerHTML = index;
						if (index == requestedPage) link.addClassName("selected")
						index++;
					}
					else if (link.hasClassName("pagingprevious"))
					{
						if (requestedPage == 1) link.addClassName("disabled")
						else link.removeClassName("disabled")
					}
					else if (link.hasClassName("pagingnext"))
					{
						if (requestedPage == totalPageCount) link.addClassName("disabled")
						else link.removeClassName("disabled")
					}
				}
			);
		}
	);

	$$("div.pageditemsdisplayed").each(function(itemdisplay)
		{
			$A(itemdisplay.getElementsByClassName("range")).each(function(range)
				{
					range.innerHTML = (itemsIndex + 1) + " - " + (itemsIndex + itemsCount);
				}
			);
		}
	);
	
	this._currentPage = requestedPage;
}
