<?php

namespace App\Event;

use Doctrine\ORM\EntityManager;
use App\Entity\Niveau01;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use App\Service\LdapService;

class SyncNiveau01 implements EventSubscriber
{
    protected $container;
    protected $em;
    protected $ldap;
    protected $shouldSync;
    protected $changeSiren;
    protected $changeLabel;
    protected $oldid;
    protected $baseNiveau01;

    public function __construct($container, EntityManager $em, LdapService $ldap) {
        $this->container = $container;
        $this->em = $em;
        $this->ldap = $ldap;

        $this->shouldSync = true;
        $this->changeSiren = true;
        $this->changeLabel = true;
    }

    public function getSubscribedEvents()
    {
        return array(
            'postPersist',
            'preUpdate',
            'postUpdate',
            'preRemove'
        );
    }

    public function preUpdate(PreUpdateEventArgs $args) {

        $entity = $args->getEntity();

        if(!($entity instanceof Niveau01)) return;

        // Synchronisation uniquement si changement de valeur
        $this->shouldSync = $args->hasChangedField('label')||$args->hasChangedField('siren');
        $this->changeSiren = $args->hasChangedField('siren');
        $this->changeLabel = $args->hasChangedField('label');
        
        if($args->hasChangedField('label')) $this->oldid=$args->getOldValue('label');

        
    }

    public function postUpdate(LifecycleEventArgs $args)
    {
        $entity = $args->getEntity();

        // On met à jour/créé la fiche de l'utilisateur dans l'annuaire
        if ($entity instanceof Niveau01 && $this->shouldSync) {
            $this->upsertNiveau01($entity);
        }


        if ($entity instanceof Niveau01 && ($this->changeSiren||$this->changeLabel)) {
            // On change le SIRET de l'ensemble des utlisateurs associés à ce Niveau01
            // Pas de déclencheur bdd car trop long
            // La synchronisation journalière mettra à jour l'annuaire de l'utilisateur
            $qb = $this->em->createQueryBuilder();
            $q = $qb->update('App\Entity\User','user')
                    ->set('user.labelniveau01', $qb->expr()->literal($entity->getLabel()))
                    ->set('user.siren', $qb->expr()->literal($entity->getSiren()))
                    ->where('user.niveau01 = :niveau01')
                    ->setParameter("niveau01", $entity->getId())
                    ->getQuery();
            $q->execute();
        } 
    }

    public function postPersist(LifecycleEventArgs $args)
    {
        $entity = $args->getEntity();

        // On créait une fiche pour l'usager dans l'annuaire
        if ($entity instanceof Niveau01) {
            $this->upsertNiveau01($entity);
        }
    }

    public function preRemove(LifecycleEventArgs $args)
    {
        $entity = $args->getEntity();

        if ($entity instanceof Niveau01) {
            $this->removeNiveau01($entity);
        }
    }

    public function removeNiveau01($niveau01) {
        if($this->ldap->isEnabled()) {
            // On recherche l'utilisateur dans l'annuaire
            $criteria = '(cn='.$niveau01->getLabel().')';
            $subbranch=$this->baseNiveau01;
            $results = $this->ldap->search($criteria, array('uid'), $subbranch);

            if(count($results)) {
                $this->ldap->deleteNiveau01($niveau01);
            }
        }       
    }

    public function upsertNiveau01($niveau01, $force = false)
    {
        if($this->ldap->isEnabled()) {
            // On recherche le niveau01 dans l'annuaire
            if(isset($this->oldid))
                $criteria = '(cn='.$this->oldid.')';
            else
                $criteria = '(cn='.$niveau01->getLabel().')';


            $subbranch=$this->baseNiveau01;
            $results = $this->ldap->search($criteria, array('cn'), $subbranch);

            // Mise à jour si elle existe
            if(count($results) > 0) {
                $this->ldap->modifyNiveau01($niveau01,$this->oldid);
            }
            // Sinon création de la fiche
            else {
                $this->ldap->addNiveau01($niveau01);
            }

        }
    }

    public function getBaseNiveau01() {
        return $this->baseNiveau01;
    }

    public function setBaseNiveau01($baseNiveau01) {
        $this->baseNiveau01 = $baseNiveau01;
        return $this;
    }    
}
