<?php

/**
 * Goweb Sitemanager 5 Framework
 * 
 * @version    5.0.18
 * @category   Goweb
 * @package    Goweb_Paginator
 * @author     I&D <dev@goweb.pt>, Pedro Pinto <ppinto@goweb.pt>
 * @copyright  2009 (c) Goweb (http://www.goweb.pt)
 */

/**
 * Classe de ligacao e base de dados
 *
 * @version    5.0.18
 * @category   Goweb
 * @package    Goweb_Paginator
 * @author     I&D <dev@goweb.pt>, Pedro Pinto <ppinto@goweb.pt>
 * @copyright  2009 (c) Goweb (http://www.goweb.pt)
 */
class Goweb_Paginator {

    /**
     * Url para ser mostrado
     *
     * @var  $link
     */                 
    protected $_link = '?page=';
    
    /**
     * Offset da paginacao
     *
     * @var  $offset
     */
    protected $_offset = 0;

    /**
     * Pagina actual
     *
     * @var  $page
     */
    protected $_page = 1;

    /**
     * Nemero de resultados a mostrar por página
     *
     * @var  $rowsPerPage
     */    
    protected $_rowsPerPage = 5;

    /**
     * Nemero de links a mostrar por página
     *
     * @var  $linksPerPage
     */            
    protected $_linksPerPage = 5;
    
    /**
     * Nemero total de resultados
     *
     * @var  $totalRows
     */        
    protected $_totalRows = 0;
    
    /**
     * Nemero total de páginas
     *
     * @var  $totalPages
     */            
    protected $_totalPages = 0;

    /**
     * Total de links a mostrar por página
     *
     * @var  $totalLinksPerPage
     */
    protected $_totalLinksPerPage = 0;
  
    /**
     * Constructor
     *
     * @param   string  $link          Url para ser mostrado
     * @param   int     $totalRows     Numero total de resultados
     * @param   int     $page          Pagina actual
     * @param   int     $rowsPerPage   Numero de resultados a mostrar por página
     * @param   int     $linksPerPage  Total de links a mostrar por página
     */
    public function __construct($link, $totalRows, $page = 1, $rowsPerPage = 10, $linksPerPage = 10) {
        $baseUrl = str_replace('/admin', '', Zend_Controller_Front::getInstance()->getRequest()->getBaseUrl());
        if (strlen($baseUrl) > 0 && strpos($link, $baseUrl) !== 0) $link = $baseUrl . $link;
        $this->_link = $link;
        $this->_totalRows = (int) $totalRows;
        $this->_page = (int) $page;
        $this->_rowsPerPage = (int) $rowsPerPage;
        $this->_linksPerPage = (int) $linksPerPage;

        if (!($this->_totalRows > 0)) {
            $this->_totalRows = 0;
        }

        if (!($this->_page > 0)) {
            $this->_page = 1;
        }

        $this->_totalPages        = $this->_getTotalPages();
        if ($this->_page > $this->_totalPages) {
            $this->_page = $this->_totalPages;
        }
        $this->_offset            = $this->_getOffset();
        $this->_totalLinksPerPage = $this->_getTotalLinksPerPage();
    }    

    /**
     * Retorna a página actual
     * 
     * @return  int  Retorna a página actual
     */
    public function getPage() {
        return $this->_page;
    }
    
    /**
     * Retorna a página actual (alias do getPage())
     * 
     * @return  int  Retorna a página actual
     */
    public function getCurrentPage() {
        return $this->_page;
    }    
    
    /**
     * Devolve o offset
     *
     * @return  int  Offset
     */          
    public function getOffset() {
        return $this->_offset;
    }

    /**
     * Devolve o total de resultados por página
     * Para que funcione correctamente com sql server só deve retornar os que faltam mostrar(quando na última página),
     * esta alteração não interfere com os restantes Sistemas de Base de Dados
     *
     * @return  int  Total de resultados por página
     */          
    public function getRowsPerPage() {
        //($this->_page > ($this->_totalRows/$this->_rowsPerPage)) ? $this->_totalRows % $this->_rowsPerPage : $this->_rowsPerPage;
        return $this->_rowsPerPage; 
    }

    /**
     * Devolve o total de página
     *
     * @return  int  Total de página
     */          
    public function getTotalPages() {
        return $this->_totalPages;
    }

    /**
     * Devolve o total de resultados
     *
     * @return  int  Total de resultados
     */          
    public function getTotalRows() {
        return $this->_totalRows;
    }
    
    /**
     * Devolve o HTML do primeiro bloco
     *
     * @return  string/FALSE  HTML do botco anterior ou FALSE se n&atilde;o existir
     */          
    public function getFirstLink() {
        if ($this->_totalPages <= 1 || $this->_page <= 1) {
            return false;
        } else {            
            return (strpos($this->_link, urlencode('{{page}}')) === false ? $this->_link . 1 : str_replace(urlencode('{{page}}'), 1, $this->_link));
        }
    }
    
    /**
     * Devolve o HTML do ultimo bloco
     *
     * @return  string/FALSE  HTML do botco anterior ou FALSE se n&atilde;o existir
     */          
    public function getLastLink() {
        if ($this->_totalPages <= 1 || $this->_page == $this->_totalPages ) {
            return false;
        } else {            
            return (strpos($this->_link, urlencode('{{page}}')) === false ? $this->_link . $this->_totalPages : str_replace(urlencode('{{page}}'), $this->_totalPages, $this->_link));
        }
    }

    /**
     * Devolve o HTML do botco anterior
     *
     * @return  string/FALSE  HTML do botco anterior ou FALSE se n&atilde;o existir
     */          
    public function getPrevLink() {
        if ($this->_page <= 1) {
            return false;
        } else {
            return (strpos($this->_link, urlencode('{{page}}')) === false ? $this->_link . ($this->_page - 1) : str_replace(urlencode('{{page}}'), ($this->_page - 1), $this->_link));
        }
    }

    /**
     * Devolve o HTML do botco preximo
     *
     * @return  string/FALSE  HTML do botco anterior ou FALSE se n&atilde;o existir
     */          
    public function getNextLink() {
        if (($this->_page) >= $this->_totalPages) {
            return false;
        } else {
            return (strpos($this->_link, urlencode('{{page}}')) === false ? $this->_link . ($this->_page + 1) : str_replace(urlencode('{{page}}'), ($this->_page + 1), $this->_link));
        }
    }

    /**
     * Retorna um array com os links
     * 
     * @return  array  Array com os links
     */
    public function getLinks() {
        $links = array();
        
        $start = $this->_page - floor($this->_linksPerPage / 2);        
        if ($start < 1) {
            $start = 1;
        }
        
        $end = $start + ($this->_linksPerPage - 1);

        if ($end >= $this->_totalPages) {
            $end = $this->_totalPages;
            $start = ($end - ($this->_linksPerPage - 1) < 1 ? 1 : $end - ($this->_linksPerPage - 1));
        }

        for ($i = $start; $i <= $end; $i++) {
            $links[] = array('page' => $i,
                             'link' => strpos($this->_link, urlencode('{{page}}')) === false ? $this->_link . $i : str_replace(urlencode('{{page}}'),$i,$this->_link));
        }

        return $links;
    }    
    
    /**
     * Metodos private/protected
     */

    /**
     * Calcula o total de páginas
     *
     * @return  int  Total de páginas
     */
    protected function _getTotalPages() {
        if ($this->_totalRows > 0 && $this->_rowsPerPage > 0) {
            return (int) ceil($this->_totalRows / $this->_rowsPerPage);
        } else {
            return 1;
        }
    }

    /**
     * Devolve o offset
     *
     * @return  int  Offset
     */  
    protected function _getOffset() {
        return ($this->_page == 1 ? 0 : (($this->_page - 1) * $this->_rowsPerPage));
    }

    /**
     * Devolve o total de links por página;
     *
     * @return  int  Total de links por página;
     */      
    protected function _getTotalLinksPerPage() {
        if ($this->_linksPerPage > 0) {
            return (int) ceil($this->_totalPages / $this->_linksPerPage);
        } else {
            return 0;
        }
    }
}