<?php

namespace App\Event;

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

class SyncNiveau02 implements EventSubscriber
{
    protected $container;
    protected $em;
    protected $ldap;
    protected $shouldSync;
    protected $changeSiret;
    protected $changeLabel;
    protected $oldid;
    protected $baseNiveau02;

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

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

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

    public function preUpdate(PreUpdateEventArgs $args) {

        $entity = $args->getEntity();

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

        // Synchronisation uniquement si changement de valeur
        $this->shouldSync = $args->hasChangedField('label')||$args->hasChangedField('siret')||$args->hasChangedField('postaladress');
        $this->changeSiret = $args->hasChangedField('siret');
        $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 Niveau02 && $this->shouldSync) {
            $this->upsertNiveau02($entity);
        }

        if ($entity instanceof Niveau02 && ($this->changeSiret||$this->changeLabel)) {
            // On change le SIREN de l'ensemble des utlisateurs associés à ce Niveau02
            // 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.labelniveau02', $qb->expr()->literal($entity->getSiret()))
                    ->set('user.siret', $qb->expr()->literal($entity->getSiren()))
                    ->where('user.niveau02 = :niveau02')
                    ->setParameter("niveau02", $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 Niveau02) {
            $this->upsertNiveau02($entity);
        }
    }

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

        if ($entity instanceof Niveau02) {
            $this->removeNiveau02($entity);
        }
    }

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

            if(count($results)) {
                $this->ldap->deleteNiveau02($niveau02);
            }
        }      
    }

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

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

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

    public function getBaseNiveau02() {
        return $this->baseNiveau02;
    }

    public function setBaseNiveau02($baseNiveau02) {
        $this->baseNiveau02 = $baseNiveau02;
        return $this;
    }    
}
