<?php

namespace Cadoles\CoreBundle\EventListener;

use Cadoles\CoreBundle\Entity\User;
use Cadoles\CoreBundle\Entity\Group;
use Cadoles\CoreBundle\Entity\UserGroup;

use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use Doctrine\ORM\EntityManager;
use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\Exception\UnsatisfiedDependencyException;

class syncUser implements EventSubscriber
{
    protected $container;
    protected $shouldSync;
    protected $shouldSyncpwd;
    protected $baseUser;
    protected $ldap_username;

    public function __construct($container, EntityManager $em, $ldap_username) {
        $this->container = $container;
        $this->em = $em;
        $this->shouldSync = true;
        $this->shouldSyncpwd = true;
        $this->ldap_username = $ldap_username;
    }

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

    public function preUpdate(PreUpdateEventArgs $args) {

        $entity = $args->getEntity();

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

        // Synchronisation uniquement si changement de valeur
        $this->shouldSync = $args->hasChangedField('username') ||
                            $args->hasChangedField('firstname') ||
                            $args->hasChangedField('lastname') ||
                            $args->hasChangedField('email') ||
                            $args->hasChangedField('role') ||
                            $args->hasChangedField('avatar') ||
                            $args->hasChangedField('niveau01') ||
                            $args->hasChangedField('niveau02') ||
                            $args->hasChangedField('siren') ||
                            $args->hasChangedField('siret') ||
                            $args->hasChangedField('labelniveau01') ||
                            $args->hasChangedField('labelniveau02') ||
                            $args->hasChangedField('authlevel') ||
                            $args->hasChangedField('usualname') ||
                            $args->hasChangedField('telephonenumber') ||
                            $args->hasChangedField('postaladress') ||
                            $args->hasChangedField('givensname') ||
                            $args->hasChangedField('birthdate') ||
                            $args->hasChangedField('gender') ||
                            $args->hasChangedField('job') ||
                            $args->hasChangedField('position') ||
                            $args->hasChangedField('belongingpopulation') ||
                            $args->hasChangedField('birthcountry') ||
                            $args->hasChangedField('birthplace')
                            ;

        $this->shouldSyncpwd = $args->hasChangedField('password');

        $entity->setSiren($entity->getNiveau01()->getSiren());
        $entity->setLabelniveau01($entity->getNiveau01()->getLabel());
        if($entity->getNiveau02()!==null) {
            $entity->setSiret($entity->getNiveau02()->getSiret());
            $entity->setLabelniveau02($entity->getNiveau02()->getLabel());
        }
        else {
            $entity->setSiret(null);
            $entity->setLabelniveau02(null);
        }
    }

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


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

        // On met à jour/créé le password de l'utilisateur dans l'annuaire
        if ($entity instanceof User && $this->shouldSyncpwd) {
            $this->upsertUserpwd($entity);
        }        
    }

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

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

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

        if ($entity instanceof User) {
            $this->removeUser($entity);
        }
    }

    public function removeUser($user) {
        // Synchonisation LDAP
        $ldap = $this->container->get('cadoles.core.service.ldap');
        if($ldap->isEnabled()) {
            // On recherche l'utilisateur dans l'annuaire
            $criteria = '('.$this->ldap_username.'='.$user->getUsername().')';
            $subbranch=$this->baseUser;
            $results = $ldap->search($criteria, array($this->ldap_username), $subbranch);

            if(count($results)) {
                $ldap->deleteUser($user);
            }
        }
        
        // Synchronisation Onlyoffice
        $only = $this->container->get('cadoles.core.service.only');
        if($only->isEnabled()) {
            $only->delUser($user);
        }        
    }

    public function upsertUser($user, $force = false)
    {
        // Synchonisation LDAP
        $ldap = $this->container->get('cadoles.core.service.ldap');
        if($ldap->isEnabled()) {
            // On recherche l'utilisateur dans l'annuaire
            $criteria = '('.$this->ldap_username.'='.$user->getUsername().')';
            $subbranch=$this->baseUser;
            $results = $ldap->search($criteria, array($this->ldap_username), $subbranch);

            // Mise à jour si elle existe
            if(count($results) > 0) {
                $ldap->modifyUser($user);
            }
            // Sinon création de la fiche
            else {
                $ldap->addUser($user);
            }

            $ldap->addGroupUser($user);
        }

        // Synchronisation Onlyoffice
        $only = $this->container->get('cadoles.core.service.only');
        if($only->isEnabled()) {
            $only->syncUser($user);
        }

        // On ajoute l'utilisateur au groupe 'Tout le Monde' quoi qu'il arrive
        $fgall=$this->em->getRepository('CadolesCoreBundle:Group')->findBy(array('fgall'=>true));
        if($fgall) {
            $data=$this->em->getRepository('CadolesCoreBundle:UserGroup')->findBy(array('user'=>$user,'group'=>$fgall[0]));
            if(!$data) {
                $key = Uuid::uuid4();
                $data=new UserGroup();
                $data->setUser($user);
                $data->setGroup($fgall[0]);
                $data->setKeyvalue($key);
                $data->setRolegroup(0);
                $this->em->persist($data);
                $this->em->flush();            
            }
        }            
    }

    public function upsertUserpwd($user, $force = false)
    {
        // Synchonisation LDAP
        $ldap = $this->container->get('cadoles.core.service.ldap');
        if($ldap->isEnabled()) {
            // On recherche l'utilisateur dans l'annuaire
            $criteria = '('.$this->ldap_username.'='.$user->getUsername().')';
            $subbranch=$this->baseUser;
            $results = $ldap->search($criteria, array($this->ldap_username), $subbranch);

            // Mise à jour si elle existe
            if(count($results) > 0) {
                $ldap->modifyUserpwd($user);
            }
        }
    }

    public function getBaseUser() {
        return $this->baseUser;
    }

    public function setBaseUser($baseUser) {
        $this->baseUser = $baseUser;
        return $this;
    }       
}
