Paginator = function(totalResults, offset, resultsPerPage, numPages) {
    if(!numPages) {
        numPages = 9;
    }

    PaginatorPage = function(page) {

        this.getFirstRecord = function() {
            var ret = (page - 1) * resultsPerPage + 1;
            return (+ret) > (+totalResults) ? totalResults : ret;
        }

        this.getLastRecord = function() {
            var ret = (+this.getFirstRecord()) + (+resultsPerPage) - 1;
            return (+ret) >  (+totalResults) ? totalResults : ret;
        }

        this.getPage = function() {
            return page;
        }

        this.isCurrentPage = function() {
            return offset / resultsPerPage + 1 == page;
        }

    }

    this.getCurrentPage = function() {
        return new PaginatorPage(offset / resultsPerPage + 1);
    }

    this.getFirstPage = function() {
        return new PaginatorPage(totalResults > 0 ? 1 : 0);
    }

    this.getLastPage = function() {
        return new PaginatorPage(this.getPageCount());
    }

    this.getNextPage = function() {
        return new PaginatorPage(offset / resultsPerPage + 2);
    }

    this.getPreviousPage = function() {
        return new PaginatorPage(offset / resultsPerPage);
    }

    this.getPageCount = function() {
        return Math.ceil(totalResults /resultsPerPage);
    }

    this.getPages = function() {
        var currentPage = offset / resultsPerPage + 1;
        var possiblePages = this.getPageCount();
        var halfPages = Math.floor((numPages - 1) / 2);
        var firstPage = currentPage - halfPages;
        if(firstPage + halfPages * 2 > possiblePages) {
            firstPage += possiblePages - (firstPage + halfPages * 2);
        }
        if(firstPage < 1) {
            firstPage = 1;
        }
        var ret = new Array();
        for(var i = 0; i < numPages && (i + firstPage - 1) * resultsPerPage < totalResults; i++) {
            var page = new PaginatorPage(i + firstPage);
            ret[i] = page;
        }
        return ret;
    }

    this.getTotalResults = function() {
        return totalResults;
    }

    this.isPaginated = function() {
        return totalResults > resultsPerPage;
    }

    this.isShowNext = function() {
        return (+offset) + (+resultsPerPage) <  +totalResults;
    }

    this.isShowPrevious = function() {
        return offset > 0;
    }

}
