*
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see .
 */
namespace Chill\MainBundle\Templating\Widget;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Chill\MainBundle\Templating\Widget\WidgetInterface;
use Chill\MainBundle\Templating\Events\DelegatedBlockRenderingEvent;
/**
 * Add the function `chill_delegated_block`.
 * 
 * In a template, you can now allow rendering of a block from other bundle.
 *  
 *  The layout template must explicitly call the rendering of other block,
 *  with the twig function
 *  
 *  ```
 *  chill_delegated_block('block_name', { 'array' : 'with context' } )
 *  ```
 *  
 *  This will launch an event
 *  `Chill\MainBundle\Templating\Events\DelegatedBlockRenderingEvent` with
 *  the event's name 'chill_block.block_name'.
 *  
 *  You may add content to the page using the function
 *  `DelegatedBlockRenderingEvent::addContent`.
 * 
 * See also the documentation of 
 * `Chill\MainBundle\Templating\Events\DelegatedBlockRenderingEvent`
 * for usage of this event class
 * 
 *
 * @author Julien Fastré 
 */
class WidgetRenderingTwig extends \Twig_Extension
{
    
    /**
     * Contains the widget. This is a double dimension array :
     * 
     * - first key is the place,
     * - second key is the ordering ;
     * - the value is an array where the widget is the first argument and the 
     * second is the config
     * 
     * i.e :
     * 
     * $widget['place']['ordering'] = array($widget, $config);
     * 
     * 
     * 
     * @var array an array of widget by place and ordering
     */
    protected $widget = array();
    
    /**
     *
     * @var EventDispatcherInterface
     */
    protected $eventDispatcher;
    
    public function __construct(EventDispatcherInterface $eventDispatcher)
    {
        $this->eventDispatcher = $eventDispatcher;
    }
    
    
    public function getName()
    {
        return 'chill_main_widget';
    }
    
    public function getFunctions()
    {
        return array(
            new \Twig_SimpleFunction('chill_delegated_block', 
                    array($this, 'renderingWidget'),
                    array(
                        'is_safe' => array('html'), 
                        'needs_environment' => true,
                        'deprecated' => true, 'alternative' => 'chill_widget'
                        )),
            new \Twig_SimpleFunction('chill_widget', 
                    array($this, 'renderingWidget'),
                    array('is_safe' => array('html'), 'needs_environment' => true))
        );
    }
    
    public function renderingWidget(\Twig_Environment $env, $block, array $context = array())
    {
        // get the content of widgets
        $content = '';
        foreach ($this->getWidgetsArraysOrdered($block) as $a) {
            /* @var $widget Widget\WidgetInterface */
            $widget = $a[0];
            $config = $a[1];
            
            $content .= $widget->render($env, $block, $context, $config);
        }
        
        // for old rendering events (deprecated)
        $event = new DelegatedBlockRenderingEvent($context);
        
        $this->eventDispatcher->dispatch('chill_block.'.$block, $event);
        
        return $content." ".$event->getContent();
    }
    
    /**
     * add a widget to this class, which become available for a future call.
     * 
     * This function is used by DependencyInjection\CompilerPass\WidgetCompilerPass, 
     * which add the widget to this class when it is created by from DI, according
     * to the given config under `chill_main`.
     * 
     * @param string $place
     * @param WidgetInterface $widget
     * @param array $config
     */
    public function addWidget($place, $ordering, $widget, array $config = array())
    {
        $this->widget[$place][$ordering] = array($widget, $config);
    }
    
    /**
     * 
     * @param string $place
     * @return array
     */
    protected function getWidgetsArraysOrdered($place)
    {
        if (!array_key_exists($place, $this->widget)) {
            $this->widget[$place] = array();
        }
        
        \ksort($this->widget[$place]);
        
        return $this->widget[$place];
    }
    
    
}