/**
 * Create a new Paging object with the given page size, the given container
 * element id and the prefix of each item element id.
 * 
 * @param pageSize
 *          the size of each shown page (in number of items)
 * @param containerId
 *          the id of the container containing the items
 * @param itemId
 *          the beginning of the item id (without the number). If the items
 *          have ids like 'item1', 'item2', 'item3', etc., this would be 'item'
 * 
 * @author kai
 *
 */
function Paging(pageSize, containerId, itemId) {
  this.currentPageIndex = -1;
  this.pageSize = pageSize;
  this.isPageAnimating = false;
  this.itemId = itemId;
  this.containerId = containerId;
  this.pageItemOffset = 1;
  this.pageDown = 0;

  // The total number of sub story entries
  this.numberOfEntries = function() {
    var size = jQuery('#' + this.containerId + ' > div[id^="' + this.itemId + '"]').length;
    return size-this.pageDown;
  };
  
  this.setPageDown = function(someNum) {
	this.pageDown = someNum;
  }
  
  this.setPageItemOffset = function(pageItemOffset) {
    this.pageItemOffset = pageItemOffset;
  }
  
  this.getPageItemOffset = function() {
    return this.pageItemOffset;
  }
  
  this.showFirstPage = function() {
    this.showPage(0);
  };
  
  this.showLastPage = function() {
    this.showPage(this.numberOfPages() - 1);
  };
  
  this.showNextPage = function() {
    if (this.isPageAnimating) {
      return;
    }
    if (this.currentPageIndex < this.numberOfPages() - 1) {
      this.showPage(this.currentPageIndex + 1);
    } else {
      this.showFirstPage();
    }
  };
  
  this.showPreviousPage = function() {
    if (this.isPageAnimating) {
      return;
    }
    if (this.currentPageIndex > 0) {
      this.showPage(this.currentPageIndex - 1);
    } else {
      this.showLastPage();
    }
  };
  
  this.numberOfPages = function() {
    var n = Math.floor(this.numberOfEntries() / this.pageSize);
    if (n * this.pageSize < this.numberOfEntries()) {
      n++;
    }
    return n;
  };
  
  // Create an array with elements ranging from 'from' to 'to'
  this.range = function(from, to) {
    var arr = new Array(to - from + 1);
    for (var i = from; i <= to; i++) {
      arr[i - from] = i;
    }
    return arr;
  };
  
  this.pageStartIndex = function(pageIndex) {
    return pageIndex * this.pageSize;
  };
  
  this.pageEndIndex = function(pageIndex) {
    var i = (pageIndex + 1) * this.pageSize - 1;
    if (i > this.numberOfEntries() - 1) {
      i = this.numberOfEntries() - 1;
    }
    return i;
  };
  
  this.showPageItem = function(itemIndex, onFadeInComplete) {
    if (onFadeInComplete != null) {
      jQuery("#" + this.itemId + (itemIndex + this.pageItemOffset)).fadeIn('slow', onFadeInComplete);
    } else {
      jQuery("#" + this.itemId + (itemIndex + this.pageItemOffset)).fadeIn('slow');
    }
  };
  
  this.hidePageItem = function(itemIndex, onFadeOutComplete) {
    if (onFadeOutComplete != null) {
      jQuery("#" + this.itemId + (itemIndex + this.pageItemOffset)).fadeOut('slow', onFadeOutComplete);
    } else {
      jQuery("#" + this.itemId + (itemIndex + this.pageItemOffset)).fadeOut('slow');
    }
  };
  
  this.hidePage = function(pageIndex, onHideComplete) {
    var pagingObject = this;
    if (pageIndex >= 0 && pageIndex < this.numberOfPages()) {
      jQuery.each(pagingObject.range(pagingObject.pageStartIndex(pageIndex), pagingObject.pageEndIndex(pageIndex)), function(index, item) {
        if (index == 0) {
          // Register callback for fade-out on first item
          pagingObject.hidePageItem(item, onHideComplete);
        } else {
          pagingObject.hidePageItem(item, null);
        }
      });
    } else {
      onHideComplete();
    }
  };
  
  this.showPage = function(pageIndex) {
    if (this.currentPageIndex == pageIndex) {
      return;
    }
    // Hide current page
    var pagingObject = this;
    this.isPageAnimating = true;
    this.hidePage(this.currentPageIndex, function() {
      // If hiding has finished, show new page
      jQuery.each(pagingObject.range(pagingObject.pageStartIndex(pageIndex), pagingObject.pageEndIndex(pageIndex)), function(index, item) {
        pagingObject.showPageItem(item, function() {
          // If show is finished, reset 'isPageAnimating' to false
          pagingObject.isPageAnimating = false;
          // Update index of currently shown page
          pagingObject.currentPageIndex = pageIndex;
        });
      });
    });
  };

}

