<?php
/**
 * Add MetaTagSet to TaggableContentInterface Entities when not already added.
 * In most cases this is used when no form is added to an entity form
 *
 * @author Elze Kool <info@visualmedia.nl>
 */

namespace VisualM\TagManagerBundle\Doctrine\EventListener;

use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Event\PostFlushEventArgs;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use VisualM\TagManagerBundle\Content\TaggableContentInterface;
use VisualM\TagManagerBundle\Entity\MetaTag;


/**
 * Add MetaTagSet to TaggableContentInterface Entities when not already added.
 *
 * @author Elze Kool <info@visualmedia.nl>
 */
class AddMetaTagSetSubscriber implements EventSubscriber, ContainerAwareInterface
{
    use ContainerAwareTrait;
    
    /**
     * Needs Flush
     * @var bool
     */
    private $needsFlush = false;
    
    /**
     * Specifies the list of events to listen
     *
     * @return array
     */
    public function getSubscribedEvents()
    {
        return array(
            'postPersist',
            'postFlush'
        );
    }
    /**
     * postPersist event
     *
     * @param LifecycleEventArgs $args Event Data
     */
    public function postPersist(LifecycleEventArgs $args)
    {
        $entity = $args->getEntity();
        if (!($entity instanceof TaggableContentInterface)) {
            return;
        }

        // Determine the content names for the entity
        $content_names = $this->getContentNamesForEntity($entity);

        // If no content names are found exit
        if (count($content_names) == 0) {
            return;
        }

        // Go trough sets to determine which to add
        $meta_tag_sets = [];
        $meta_tag_set_manager = $this->container->get('visualm.tag_manager.manager.meta_tag_set');
        foreach($meta_tag_set_manager->getIndex() as $meta_tag_set) {
            if (count(array_intersect($content_names, $meta_tag_set->getContentTypes())) > 0) {
                $meta_tag_sets[] = $meta_tag_set;
            }
        }

        // If no MetaTagSets are found exit
        if (count($meta_tag_sets) == 0) {
            return;
        }

        // Get MetaTagPreset's already added to entity
        $meta_tag_preset_ids = $this->getMetaTagPresetIdsForEntity($entity);

                
        // Loop trough sets to add
        foreach($meta_tag_sets as $meta_tag_set) {

            // Get MetaTagPresets for this set
            foreach($meta_tag_set->getMetaTagPresets() as $meta_tag_preset) {

                if (in_array($meta_tag_preset->getId(), $meta_tag_preset_ids)) {
                    continue;
                }

                // Create new tag from preset
                $meta_tag = new MetaTag();
                $meta_tag->setAutoAdded(true);
                $meta_tag->setContentId($entity->getContentId());
                $meta_tag->setInhoud($meta_tag_preset->getInhoud());
                $meta_tag->setInhoudIsExpression($meta_tag_preset->getInhoudIsExpression());
                $meta_tag->setInhoudGewijzigd(false);
                $meta_tag->setZichtbaar($meta_tag_preset->getZichtbaar());
                $meta_tag->setZichtbaarIsExpression($meta_tag_preset->getZichtbaarIsExpression());
                $meta_tag->setZichtbaarGewijzigd(false);
                $meta_tag->setMetaTagPreset($meta_tag_preset);

                $args->getEntityManager()->persist($meta_tag);
                $this->needsFlush = true;


            }

        }

    }

    /**
     * Get MetaTagPresetId id's that are already added to Entity
     *
     * @param TaggableContentInterface $entity Entity
     *
     * @return array MetaTagPresetId id's
     */
    protected function getMetaTagPresetIdsForEntity(TaggableContentInterface $entity)
    {
        // Preset ids in content, load them from the database
        // and from the metaSetCollection becouse until the flush
        // is called they are not in the database
        $meta_tag_manager = $this->container->get('visualm.tag_manager.manager.meta_tag');
        $meta_tag_preset_ids = [];
        foreach($meta_tag_manager->getIndex(['content_id' => $entity->getContentId()]) as $meta_tag) {
            $meta_tag_preset_ids[] = $meta_tag->getMetaTagPreset()->getId();
        }
        if ($entity->getMetaTagCollection() !== null) {
            foreach($entity->getMetaTagCollection()->getMetaTags() as $meta_tag) {
                $meta_tag_preset_ids[] = $meta_tag->getMetaTagPreset()->getId();
            }
        }
        return $meta_tag_preset_ids;
    }

    /**
     * Get ContentNames For Entity
     *
     * @param TaggableContentInterface $entity Entity
     *
     * @return array Content Names
     */
    protected function getContentNamesForEntity(TaggableContentInterface $entity)
    {
        $content_names = [];
        $taggable_manager_registry = $this->container->get('visualm.tag_manager.util.taggable_manager_registry');
        foreach($taggable_manager_registry->getRegistratedNames() as $name) {
            $repository = $taggable_manager_registry->getManager($name);
            if ($repository->isEntityHandled($entity)) {
                $content_names[] = $name;
            }
        }
        return $content_names;
    }

    /**
     * postFlush event
     *
     * @param PostFlushEventArgs $eventArgs Event Data
     */
    public function postFlush(PostFlushEventArgs $eventArgs)
    {
        if ($this->needsFlush) {
            $this->needsFlush = false;
            $eventArgs->getEntityManager()->flush();
        }
    }

    
}
