<?php
/**
 * Paginator class
 * @author Jérôme Brilland
 * @version 4.0
 * @copyright (c) 2015-2022, Jérôme Brilland
 * @license http://www.gnu.org/licenses/gpl.txt GNU General Public License
 */
class Paginator {

    /**
     * @var int Number of items per page
     * @access private
     */
    private $itemsPerPage;

    /**
     * @var int Total number of items
     * @access private
     */
    private $totalItems;

    /**
     * @var int Current page
     * @access private
     */
    private $page;

    /**
     * @var int Last page number
     * @access private
     */
    private $lastPage;

    /**
     * @var int Offset value
     * @access private
     */
    private $offset;

    /**
     * Class constructor
     * @param integer $itemsPerPage
     * @param integer $totalItems
     * @param integer $page
     */
    public function __construct( int $itemsPerPage, int $totalItems, int $page ) {
        $this->itemsPerPage = $itemsPerPage;
        $this->totalItems = $totalItems;
        $this->setPage( $page );
    }
    
    /**
     * Returns the first page number
     * @return int
     * @access public
     */
    public function getFirstPage() {
        return 1;
    }

    /**
     * Returns the last page number
     * @return int
     * @access public
     */
    public function getLastPage() {
        if ( empty( $this->lastPage ) ) {
            if ( $this->itemsPerPage > 0 ) {
                $this->lastPage = ceil( $this->totalItems / $this->itemsPerPage );
            } else {
                $this->lastPage = 1;
            }
        }
        return $this->lastPage;
    }

    /**
     * Set the current page number
     * @param integer $page
     */
    public function setPage( int $page ) {
        // Ensures that the requested page number is within range. Note that the default is to start at page 1.
        $lastPage = $this->getLastPage();
        if ( empty( $page ) || $page <= 1 ) {
            $this->page = 1;
        } elseif ( $page > $lastPage ) { 
            $this->page = $lastPage;
        } else {
            $this->page = $page;
        }
    }

    /**
     * Returns the offset value
     * @access public
     */
    public function getOffset() {
        if ( $this->itemsPerPage > 0 ) {
            $this->offset = ( $this->page - 1 ) * $this->itemsPerPage;
        } else {
            $this->offset = null;
        }
        return $this->offset;
    }

    /**
     * Returns the limit value
     * @return integer
     * @access public
     */
    public function getLimit() {
        return $this->itemsPerPage;
    }

    /**
     * Returns the current page number
     * @return integer
     * @access public
     */
    public function getPage() {
        return $this->page;
    }

    /**
     * Return the total number of items
     * @return integer
     * @access public
     */
    public function getTotalItems() {
        return $this->totalItems;
    }
    
    /**
     * Whether the given value is a valid page number
     * @param integer $page
     * @return boolean
     * @access public
     */
    public function isValidPage( int $page ) {
        if ( !Validator::validateInteger( $page ) ) {
            return false;
        }
        return $page > 0 && $page <= $this->getLastPage();
    }

    /**
     * Is the current page the first one?
     * @return boolean
     * @access public
     */
    public function isFirst() {
        return 1 == $this->page;
    }

    /**
     * Is the current page the last one?
     * @return boolean
     * @access public
     */
    public function isLast() {
        return $this->page == $this->lastPage;
    }

}
