var Paging = new Class({
  Implements : [Options],
  options : {
     'limit'          :10
    ,'maxPagesVisible':15
    ,'pagerWidth'     :26   //The width of a page number element (margins inclusive)
    ,'pagerWidthDiff' :7    //The difference in width of the page number elements of the numbers 1-9
    ,'scrollerWidth'  :undefined  //The maximal width of the scrolling number elements in pixels, defaults to maxPagesVisible * pagerWidth
    ,'scrollDuration' :1000
    ,'pagerUrl'       :undefined
    ,'ajaxRequest'    :false
    ,'ajaxRequestHash':{}
    ,'ajaxRequestUrl' :undefined
    ,'ajaxReplaceId'  :undefined  //The id of the element that is going to be replaced by the ajax call
  },
  initialize: function(element, options){
    this.setOptions(options);
    if(this.options.pagerUrl == undefined)
    {
      this.options.pagerUrl = this.getPagerUrl();
    }
    this.options = $merge(this.options, (JSON.decode(element.getElement('.paging_options').get('text'))));
    this.paging = element;
    this.scrollBox = this.paging.getElement('div.scrollbox');
    this.scrollPane = this.paging.getElement('div.scrollpane');
    this.totalPages = this.paging.getElement('a.rrpage').getProperty('href').split('/').getLast().toInt();
    this.currentPage = this.paging.getElement('a.currentPage');
    if(this.options.scrollerWidth == undefined)
    {
      this.options.scrollerWidth = this.options.maxPagesVisible * this.options.pagerWidth
    }
    var pagersPresent = this.paging.getElements('a.num');
    var firstPagerPresent = pagersPresent[0].get('text').toInt();
    var lastPagerPresent = pagersPresent.getLast().get('text').toInt();
    
    this.setScrollProperties();
    this.addPagers(1, firstPagerPresent-1, 'top');
    this.addPagers(lastPagerPresent+1, this.totalPages, 'bottom');
    this.addEvents(this.paging.getElements('a'));
    var position = this.currentPage.getPosition(this.scrollBox);
    this.scroller.set(position.x-this.xOffset,position.y);
    this.scroller.toElement(this.currentPage);
    var requestOptions = {
        'url':this.options.ajaxRequestUrl
      , 'method':'post'
    }
    this.pageRequest = new Request(requestOptions);
    this.pageRequest.onSuccess = this.processAjaxRequest.bind(this);
  },
  setScrollProperties: function(){
    var maxPagesVisible = this.options.maxPagesVisible;
    var totalPages = this.totalPages;
    var pagerWidth = this.options.pagerWidth;
    var pagerWidthDiff = this.options.pagerWidthDiff
    
    this.scrollBox.setStyle('text-align','left');
    var totalSmallPagers = Math.min(9,totalPages);
    if(totalPages <= maxPagesVisible)
    {
      var scrollBoxWidth = pagerWidth * (totalPages)
      scrollBoxWidth -= totalSmallPagers*pagerWidthDiff;
      this.scrollBox.setStyle('width', scrollBoxWidth);
    }
    else
    {
      //TODO:use max-width?
      this.scrollBox.setStyle('width', this.options.scrollerWidth);
    }
    this.xOffset = (this.scrollBox.getStyle('width').toInt()/2)-(pagerWidth/2);
    var scrollPaneWidth = (pagerWidth * totalPages) + (this.xOffset - totalSmallPagers*pagerWidthDiff);
    this.scrollPane.setStyle('width', scrollPaneWidth);
    this.scroller = new Fx.Scroll(this.scrollBox, {
    	wait: false,
    	duration: this.options.scrollDuration,
    	offset: {'x': -this.xOffset, 'y': 0},
    	transition: Fx.Transitions.linear
    });
  },
  addPagers: function(fromPager, toPager, where){
    var pagersToInject = document.createElement('span');
    for(var i = fromPager; i <= toPager; i++)
    {
      var newPager = this.createPager(i);
      newPager.inject(pagersToInject);
    }
    $(pagersToInject).inject(this.scrollPane, where)
  },
  createPager: function(pageId){
    var pager = this.paging.getElement('a[class^=page_]').clone();
    pager.set('text',pageId);
    pager.removeProperty('class');
    pager.addClass('page_'+pageId);
    pager.addClass('num');
    pager.setProperty('href', this.options.pagerUrl+pageId);
    return pager;
  },
  addEvents: function(elements){
    elements.each(function(pager, index){
      if(pager.hasClass('num'))
      {
        pager.addEvent('mouseover', function(e) {
          this.toElement(pager);
        }.bindWithEvent(this.scroller));
      }
      pager.addEvent('click', this.pagerClicked.bindWithEvent(this, pager));   
    }.bind(this));
  },
  getPagerUrl: function() {
    var location = new String(document.location);
    if(location.contains('p','/'))
    {
      location = location.split('/p/')[0];
    }
    return location + '/p/';
  },
  pagerClicked: function(e, pager) {
    if(this.options.ajaxRequest) new Event(e).stop();
    var activeItem;
    this.pageNumber = 1;
    if(pager.hasClass('num'))
    {
      this.pageNumber = pager.get('text');
      activeItem = pager;
    }
    else if(pager.hasClass('llpage')) this.pageNumber = 1;
    else if(pager.hasClass('lpage'))  this.pageNumber = Math.max(this.currentPage.get('text').toInt() - 1,1);
    else if(pager.hasClass('rpage'))  this.pageNumber = Math.min(this.currentPage.get('text').toInt() + 1,this.totalPages);
    else if(pager.hasClass('rrpage')) this.pageNumber = this.totalPages;
    if(!pager.hasClass('num'))
    {
      activeItem = this.paging.getElement('a.page_'+this.pageNumber);
    }
    this.doAjaxRequest(this.pageNumber);
    this.currentPage.removeClass('currentPage');
	  activeItem.addClass('currentPage');
	  this.scroller.toElement(activeItem);
	  var arrowLeft =  this.paging.getElement('a.lpage');
	  var arrowRight = this.paging.getElement('a.rpage');
	  if      (this.pageNumber <= 1 && arrowLeft.getStyle('visibility') != 'hidden')  arrowLeft.tween('opacity',1,0);
	  else if (this.pageNumber >  1 && arrowLeft.getStyle('visibility') != 'visible') arrowLeft.tween('opacity',0,1);
	  if      (this.pageNumber >= this.totalPages && arrowRight.getStyle('visibility') != 'hidden')  arrowRight.tween('opacity',1,0);
	  else if (this.pageNumber <  this.totalPages && arrowRight.getStyle('visibility') != 'visible') arrowRight.tween('opacity',0,1);
	  this.currentPage = activeItem;
  },
  doAjaxRequest: function(page_id) {
    var requestHash = $H(this.options.ajaxRequestHash);
    requestHash.extend({'page':page_id,'limit':this.options.limit});
    this.pageRequest.send(requestHash.toQueryString());
  },
  processAjaxRequest: function(responseText, responseXML)
  {
    var oldElement = $(this.options.ajaxReplaceId);
    var newElement = oldElement.clone(true, true);
    //clone doesn't keepid, apparently, so we're setting it ourselves 
    newElement.setProperty('id', this.options.ajaxReplaceId);
    newElement.empty();

    newElement.set('html', responseText);
    replace = new Fx.Replace(newElement, {'replaceId':this.options.ajaxReplaceId});
    replace.start();
  }
  
});
