<?php
/**
 * AdminList
 * 
 * @author Elze Kool <info@visualmedia.nl>
 */

namespace VisualM\ManagementBundle\AdminList;

use Symfony\Component\HttpFoundation\Request;
use VisualM\ModelManagementBundle\Definition\ModelManagerInterface;
use VisualM\ModelManagementBundle\Definition\SlidingPaginatorInterface;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\FormFactoryInterface;

/**
 * AdminList
 *
 * @author Elze Kool <info@visualmedia.nl>
 */
abstract class AdminList
{
    
    /**
     * Request
     * @var Request
     */
    protected $Request;
        
    /**
     * Manager for Model
     * @var ModelManagerInterface
     */
    protected $Manager;
    
    /**
     * Pagination Configuration
     * @var PaginationConfiguration
     */
    protected $PaginationConfiguration;
    
    /**
     * Table Configuration
     * @var ListConfiguration
     */
    protected $TableConfiguration;
    
    /**
     * Filter Configuration
     * @var FilterConfiguration
     */
    protected $ParamConfiguration;
    
    /**
     * Current Page Number
     * @var integer
     */
    protected $CurrentPage;
    
    /**
     * Current Request Parameters
     * @var array
     */
    protected $Params = array();

    /**
     * Processed filter options
     * @var array
     */
    protected $Options = array();
    
    /**
     * Current Order Field
     * @var string
     */
    protected $OrderField = null;
    
    /**
     * Current Order Field
     * @var string
     */
    protected $OrderDir = null;
    
    /**
     * SlidingPaginator
     * @var SlidingPaginatorInterface
     */
    protected $Paginator = array();


    /**
     * @param FormFactoryInterface $formFactory null als geen form
     */
    protected $FormFactory;

    /** @var Form */
    protected $BulkForm;

    /**
     * Constructor
     * 
     * @internal Do not call directly, use the AdminListFactory::create() function
     * 
     * @param Request                 $Request                 Request
     * @param ModelManagerInterface   $Manager                 ModelManager
     * @param PaginationConfiguration $PaginationConfiguration Pagination Configuration
     * @param TableConfiguration      $TableConfiguration      Table Configuration
     * @param ParamConfiguration      $ParamConfiguration      Parameter Configuration
     */
    function __construct(
        Request $Request,
        ModelManagerInterface $Manager,
        PaginationConfiguration $PaginationConfiguration,
        TableConfiguration $TableConfiguration,
        ParamConfiguration $ParamConfiguration)
    {
        $this->Request = $Request;
        $this->Manager = $Manager;
        $this->PaginationConfiguration = $PaginationConfiguration;
        $this->TableConfiguration = $TableConfiguration;
        $this->ParamConfiguration = $ParamConfiguration;
        
        $this->processRequest();
        $this->initPaginator();
        
    }

    /**
     * Process Request and determine filtering, ordering, and current page
     * 
     * @return void
     */
    protected function processRequest()
    {        
        foreach($this->ParamConfiguration->getParamProviders() as $ParamProvider) {
            $ParamProvider->process($this->Request, $this->Params, $this->Options);
        }
        
        $this->CurrentPage = isset($this->Params['page']) ? intval($this->Params['page']) : 0;        
        if (isset($this->Params['orderBy'])) {
            $this->OrderField = $this->Params['orderBy'];
            $this->OrderDir = isset($this->Params['orderDir']) ? $this->Params['orderDir'] : 'ASC';
        } else {
            $this->OrderField = $this->TableConfiguration->getDefaultOrderField();
            $this->OrderDir = $this->TableConfiguration->getDefaultOrderDir();
        }
        
    }


    /**
     * Initialize Paginator
     */
    protected function initPaginator()
    {
        $ordering = array();
        if ($this->OrderField !== null AND $this->OrderDir !== null) {
            $ordering[] = array($this->OrderField, $this->OrderDir);
        }

        $this->Paginator = $this->Manager->getSlidingPaginator(
            $this->Options, 
            $ordering, 
            $this->getPageSize(),
            $this->PaginationConfiguration->getWindowSize()
        );
    }

    /**
     * Get Page Size (Number of items per page)
     *
     * @return int Page size
     */
    public function getPageSize()
    {
        $pageSize = $this->PaginationConfiguration->getPageSize();
        if (isset($this->Params['pageSize']) AND $this->Params['pageSize'] > 0 AND $this->Params['pageSize'] < 10000) {
            $pageSize = $this->Params['pageSize'];
        }

        return $pageSize;
    }
    
    /**
     * Get Current Page Number
     * 
     * @return integer Current Page Number (0 indexed)
     */
    public function getCurrentPage()
    {
        return $this->CurrentPage;
    }
        
    /**
     * Get current Filters
     * 
     * @return array Filtering
     */
    public function getParams()
    {
        return $this->Params;
    }
    
    /**
     * Get current Order Field
     * 
     * @return array Order Field
     */
    public function getOrderField()
    {
        return $this->OrderField;
    }
    
    /**
     * Get current Ordering Direction
     * 
     * @return array Order Direction
     */ 
    public function getOrderDir()
    {
        return $this->OrderDir;
    }
    
    /**
     * Get Page Numbers
     * 
     * @return array Page Numbers (0 indexed)
     */
    public function getPageNumbers()
    {
        return $this->Paginator->getPageNumbers($this->getCurrentPage());
    }

    /**
     * Get Page Index
     * 
     * @return array Objects
     */
    public function getPageIndex()
    {
        return $this->Paginator->getPageIndex($this->getCurrentPage());
    }
    
    /**
     * Get Columns
     * 
     * @return array Column Configurations
     */
    public function getColumns()
    {
        return $this->TableConfiguration->getColumns();
    }
    
    /**
     * Return if we should render a footer
     * 
     * @return boolean Has footers
     */
    public function hasFooters()
    {
        foreach($this->getColumns() as $columnDecorator) {
            if ($columnDecorator->getColumn()->getFooterTemplate() !== null) {
                return true;
            }
        }
        return false;
    }
	
	/**
	 * Get Row Class
	 *
	 * @param mixed $item Item
	 *
	 * @return string Class
	 **/
	public function getRowClass($item) {
		return '';
	}

    public function hasBulkForm()
    {
        return null !== $this->BulkForm || null !== $this->FormFactory;
    }

    public function getBulkForm()
    {
        if (null === $this->BulkForm && $this->hasBulkForm()) {
            $this->BulkForm = $this->FormFactory->create(
                $this->getBulkFormType(),
                [],
                ['allow_extra_fields' => true,]
            );
        }
        return $this->BulkForm;
    }

    public function setBulkForm($value)
    {
        $this->BulkForm = $value;
    }

    protected function getBulkFormType()
    {
        return 'VisualM\ManagementBundle\Form\Type\BulkType';
    }

    /**
     * @return null|FormView
     */
    public function getBulkFormView()
    {
        return $this->hasBulkForm() ? $this->getBulkForm()->createView() : null;
    }
}