<?php
/**
 * Description of MetaHelper
 *
 * @author Elze Kool <info@visualmedia.nl>
 */

namespace VisualM\TagManagerBundle\Content;

use Exception;
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use VisualM\TagManagerBundle\DataCollector\TagDataCollector;
use VisualM\TagManagerBundle\Doctrine\FieldType\MetaType;
use VisualM\TagManagerBundle\Entity\MetaTag;
use VisualM\TagManagerBundle\Entity\MetaTagRepository;
use VisualM\TagManagerBundle\Util\ExtendedDataDictionary;

/**
 * Description of MetaHelper
 *
 * @author Elze Kool <info@visualmedia.nl>
 */
class MetaHelper
{
    /**
     * MetaTag Repository
     * @var MetaTagRepository
     */
    protected $metaTagManager;

    /**
     * Content Element
     * @var TaggableContentInterface
     */
    protected $content;

    /**
     * Extended DataDictionary
     * @var ExtendedDataDictionary
     */
    protected $extendedDataDictionary;

    /**
     * ExpressionLanguage
     * @var ExpressionLanguage
     */
    protected $expressionLanguage;

    /**
     * DataCollector
     * @var TagDataCollector
     */
    protected $dataCollector;

    /**
     * Constructor
     *
     * @param MetaTagRepository      $metaTagManager         MetaTag Repository
     * @param ExtendedDataDictionary $extendedDataDictionary ExtendedDataDictionary
     * @param ExpressionLanguage     $expressionLanguage     ExpressionLanguage
     * @param TagDataCollector       $dataCollector          TagDataCollector
     */
    public function __construct(MetaTagRepository $metaTagManager, ExtendedDataDictionary $extendedDataDictionary, ExpressionLanguage $expressionLanguage, TagDataCollector $dataCollector)
    {
        $this->metaTagManager = $metaTagManager;
        $this->extendedDataDictionary = $extendedDataDictionary;
        $this->expressionLanguage = $expressionLanguage;
        $this->dataCollector = $dataCollector;
    }

    /**
     * Collect Data for Object
     * 
     * @param object $object Object to collect data for
     * 
     * @return MetaHelper self
     */
    public function collectObject($object)
    {
        $this->extendedDataDictionary->pushObject($object);

        if ($object instanceof TaggableContentInterface) {
            $this->dataCollector->addCollectedContentId(sprintf('%s (%s)', join('', array_slice(explode('\\', get_class($object)), -1)), $object->getContentId()));
        } else {
            $this->dataCollector->addCollectedContentId(join('', array_slice(explode('\\', get_class($object)), -1)));
        }

        return $this;
    }

    /**
     * Set Content
     * @param TaggableContentInterface $content
     */
    public function setContent(TaggableContentInterface $content)
    {
        $this->content = $content;
        $this->dataCollector->updateContentId(sprintf('%s (%s)', join('', array_slice(explode('\\', get_class($this->content)), -1)), $this->content->getContentId()));
    }

    /**
     * Render MetaTags
     *
     * @param array $types MetaTypes to render
     * 
     * @return string Rendered tags
     */
    public function renderMetaTags($types = [])
    {
        if ($this->content === null) {
            return '';
        }

        // Get MetaTags for content
        $meta_tags = $this->metaTagManager->getIndex([ 'content_id' => $this->content->getContentId() ]);

        $rendered = '';
        foreach($meta_tags as $meta_tag) {
            if (!in_array($meta_tag->getMetaTagPreset()->getType(), $types)) { continue; }
            if (null !== ($rendered_meta_tag = $this->renderMetaTag($meta_tag))) {
                $rendered .= $rendered_meta_tag . "\n";
            }
        }
        
        return $rendered;
    }


    /**
     * Evaluate and Render MetaTag
     * 
     * @param MetaTag $metaTag MetaTag
     *
     * @return string Rendered MetaTag
     */
    protected function renderMetaTag(MetaTag $metaTag)
    {
        $data = $this->extendedDataDictionary->getData();
        foreach($data as &$value) {
            if (is_array($value)) {
                $value = (object) $value;
            }
        }

        $this->dataCollector->updateAvailableData($data);

        $language = $this->expressionLanguage;

        $exception = '';

        // In zichtbaar is null return null
        if ($metaTag->getZichtbaar() === null OR $metaTag->getZichtbaar() === null) {

            // Add line to DataCollector
            $this->dataCollector->addTag(new \VisualM\TagManagerBundle\DataCollector\CollectionItem(
                $metaTag->getMetaTagPreset()->getTitel(),
                $metaTag->getMetaTagPreset()->getType(),                
                '',
                false,
                'Zichtbaar is NULL'
            ));

            return null;
        }

        // Evaluate or set zichtbaar 
        if ($metaTag->getZichtbaarIsExpression()) {
            try { $zichtbaar = $language->evaluate($metaTag->getZichtbaar(), $data);
            } catch(Exception $e) { $zichtbaar = 0; $exception .= $e->getMessage() . PHP_EOL; }
        } else {
            $zichtbaar = $metaTag->getZichtbaar();
        }

        // Check if zichtbaar evaluates to 1, else return null
        if (intval($zichtbaar) != 1) {

            // Add line to DataCollector
            $this->dataCollector->addTag(new \VisualM\TagManagerBundle\DataCollector\CollectionItem(
                $metaTag->getMetaTagPreset()->getTitel(),
                $metaTag->getMetaTagPreset()->getType(),                
                '',
                false,
                $exception
            ));

            return null;
        }

        // Evaluate or set inhoud
        if ($metaTag->getInhoudIsExpression()) {
            try { $inhoud = $language->evaluate($metaTag->getInhoud(), $data);
            } catch(Exception $e) { $inhoud = ''; $exception .= $e->getMessage() . PHP_EOL; $zichtbaar = false; }

        } else {
            $inhoud = $metaTag->getInhoud();
        }

        if ($metaTag->getMetaTagPreset()->getType() === MetaType::META_TAG) {

            $html = sprintf(
                '<meta name="%s" content="%s" />',
                htmlspecialchars($metaTag->getMetaTagPreset()->getNaam()),
                htmlspecialchars($inhoud)
            );

        } else {
            $html = $inhoud;
        }

        // Add line to DataCollector
        $this->dataCollector->addTag(new \VisualM\TagManagerBundle\DataCollector\CollectionItem(
            $metaTag->getMetaTagPreset()->getTitel(),
            $metaTag->getMetaTagPreset()->getType(),
            $html,
            $zichtbaar,
            $exception
        ));

        return $zichtbaar ? $html : null;

    }

}
