<?php
namespace Cadoles\CoreBundle\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpKernel\KernelInterface;
use Doctrine\DBAL\Connection as DBALConnection;
use Doctrine\ORM\EntityManager;

use Cadoles\CoreBundle\Entity\Niveau01;
use Cadoles\CoreBundle\Entity\Niveau02;
use Cadoles\CoreBundle\Entity\User;
use Cadoles\CoreBundle\Entity\Group;
use Cadoles\CoreBundle\Entity\UserGroup;
use Cadoles\PortalBundle\Entity\Calendar;
use Cadoles\PortalBundle\Entity\Blog;
use Cadoles\PortalBundle\Entity\Project;

use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\Exception\UnsatisfiedDependencyException;

global $bdd01;
global $config;

class SynchroCommand extends Command
{
    private $container;
    private $em;
    private $em2;
    private $output;
    private $filesystem;
    private $rootlog;
    private $ldap;
    private $ldap_basedn;
    private $ldap_baseuser;
    private $ldap_basegroup;

    protected function configure()
    {
        $this
            ->setName('Core:Synchro')
            ->setDescription('Synchronisation Annuaire')
            ->setHelp('This command Synchro for Core')
            ->addArgument('simulate', InputArgument::OPTIONAL, 'true to simulate / false to run')            
            ->addArgument('cronid', InputArgument::OPTIONAL, 'ID Cron Job') 
            ->addArgument('lastchance', InputArgument::OPTIONAL, 'Lastchance to run the cron')              
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $this->container    = $this->getApplication()->getKernel()->getContainer();
        $this->em           = $this->container->get('doctrine')->getEntityManager();
        $this->output       = $output;
        $this->filesystem   = new Filesystem();
        $this->rootlog      = $this->container->get('kernel')->getRootDir()."/../var/logs/";

        $this->writelnred('');
        $this->writelnred('== Core:Synchro');        
        $this->writelnred('==========================================================================================================');

        setlocale( LC_CTYPE, 'fr_FR' );
        $labelniveau01  = mb_strtoupper($this->container->getParameter('labelniveau01'));
        $labelniveau02  = mb_strtoupper($this->container->getParameter('labelniveau02'));
        $masteridentity = $this->container->getParameter('masteridentity');

        $this->ldap_basedn      = $this->container->getParameter('ldap_basedn');
        $this->ldap_baseuser    = $this->container->getParameter('ldap_baseuser');
        $this->ldap_basegroup   = $this->container->getParameter('ldap_basegroup');

        $ldap_username          = strtolower($this->container->getParameter('ldap_username'));
        $ldap_firstname         = strtolower($this->container->getParameter('ldap_firstname'));
        $ldap_lastname          = strtolower($this->container->getParameter('ldap_lastname'));
        $ldap_email             = strtolower($this->container->getParameter('ldap_email'));
        $ldap_member            = strtolower($this->container->getParameter('ldap_member'));
        $scribe_group           = strtolower($this->container->getParameter('scribe_group'));

        $ldap_type              = $this->container->getParameter('ldap_type');
        $ldap_template          = $this->container->getParameter('ldap_template');
        $ldap_usersadmin        = $this->container->getParameter('ldap_usersadmin');
        $scribe_master          = strtolower($this->container->getParameter('scribe_master'));
        $fieldstoread           = array($ldap_username,$ldap_firstname,$ldap_lastname,$ldap_email);
        $ldapusers              = array();
        $ldapmails              = array();

        $simulate = $input->getArgument('simulate');
        if($simulate=="") $simulate="true";
        
        if($simulate!="true"&&$simulate!="false") {
            $this->writeln('Paramétre incorrect');
            return;
        }
        $simulate=($simulate=="true");
        
        $this->writeln('');
        if($simulate) $this->writeln('** SIMULATION');
        else $this->writeln('** REEL');

        $this->writeln('');
        $this->writeln('=====================================================');
        $this->writeln('== SYNCHONISATION ANNUAIRE ==========================');
        $this->writeln('=====================================================');

        $this->ldap = $this->container->get('cadoles.core.service.ldap');

        if(!$this->ldap->isEnabled()) {
            if($masteridentity =="LDAP") {
                $this->writeln('');
                $this->writeln('=====================================================');
                $this->writeln('== SYNCHONISATION LDAP TO BUNDLE ====================');
                $this->writeln('=====================================================');

                if($ldap_template=="scribe") {
                    $this->writeln('');
                    $this->writeln('== PROFILS ==========================================');

                    // Eleves
                    $ldapfilter="(&(uid=*)(ENTPersonProfils=eleve))";
                    $label="PROFIL - Elèves";
                    $this->writeln("    - $label");
                    if(!$simulate) $this->addmodGroup($label,$ldapfilter,false);

                    // Enseignants
                    $ldapfilter="(|(&(uid=*)(ENTPersonProfils=enseignant))(&(uid=*)(typeadmin=0))(&(uid=*)(typeadmin=2)))";
                    $label="PROFIL - Enseignants";
                    $this->writeln("    - $label");
                    if(!$simulate) $this->addmodGroup($label,$ldapfilter,false);

                    // Responsables
                    $ldapfilter="(&(uid=*)(ENTPersonProfils=responsable))";
                    $label="PROFIL - Responsables";
                    $this->writeln("    - $label");
                    if(!$simulate) $this->addmodGroup($label,$ldapfilter,false);

                    // Administratifs
                    $ldapfilter="(&(uid=*)(ENTPersonProfils=administratif))";
                    $label="PROFIL - Administratifs";
                    $this->writeln("    - $label");
                    if(!$simulate) $this->addmodGroup($label,$ldapfilter,false);

                    // Niveaux
                    $this->writeln('');
                    $this->writeln('== NIVEAUX ==========================================');
                    $results = $this->ldap->search("type=Niveau", ['cn','description','gidNumber'], $this->ldap_basedn);
                    foreach($results as $result) {
                        $cn=$result["cn"];
                        $ldapfilter="(&(type=Niveau)(cn=$cn))";

                        $label="NIVEAU - ".$result["cn"];
                        $this->writeln("    - $label");
                        if(!$simulate) $this->addmodGroup($label,$ldapfilter,false);                        
                    }

                    // Classes
                    $this->writeln('');
                    $this->writeln('== CLASSES ==========================================');
                    $results = $this->ldap->search("type=Classe", ['cn','description','gidNumber'], $this->ldap_basedn);
                    foreach($results as $result) {
                        $cn=$result["cn"];
                        $ldapfilter="(|(&(type=Classe)(cn=$cn))(&(type=Equipe)(cn=profs-$cn))(&(ENTPersonProfils=Administratif)(divcod=$cn)))";

                        $label="CLASSE - ".$result["cn"];
                        $this->writeln("    - $label");
                        if(!$simulate) $this->addmodGroup($label,$ldapfilter,$scribe_group);                        
                    }

                    // Elèves des Classes
                    $this->writeln('');
                    $this->writeln('== ELEVES DES CLASSES ==========================================');
                    $results = $this->ldap->search("type=Classe", ['cn','description','gidNumber'], $this->ldap_basedn);
                    foreach($results as $result) {
                        $cn=$result["cn"];
                        $ldapfilter="(&(type=Classe)(cn=$cn))";

                        $label="ELEVES - ".$result["cn"];
                        $this->writeln("    - $label");
                        if(!$simulate) $this->addmodGroup($label,$ldapfilter,false);                        
                    }

                    // Professeurs des Classes
                    $this->writeln('');
                    $this->writeln('== PROFESSEURS DES CLASSES ==========================================');
                    $results = $this->ldap->search("type=Classe", ['cn','description','gidNumber'], $this->ldap_basedn);
                    foreach($results as $result) {
                        $cn=$result["cn"];
                        $ldapfilter="(|(&(type=Equipe)(cn=profs-$cn))(&(ENTPersonProfils=Administratif)(divcod=$cn)))";

                        $label="PROFESSEURS - ".$result["cn"];
                        $this->writeln("    - $label");
                        if(!$simulate) $this->addmodGroup($label,$ldapfilter,false);                        
                    }

                    // Options
                    $this->writeln('');
                    $this->writeln('== OPTIONS ==========================================');
                    $results = $this->ldap->search("type=Option", ['cn','description','gidNumber'], $this->ldap_basedn);
                    foreach($results as $result) {
                        $cn=$result["cn"];
                        $ldapfilter="(|(&(type=Option)(cn=$cn))(&(type=Equipe)(cn=profs-$cn))(&(ENTPersonProfils=Administratif)(divcod=$cn)))";

                        $label="OPTION - ".$result["cn"];
                        $this->writeln("    - $label");
                        if(!$simulate) $this->addmodGroup($label,$ldapfilter,$scribe_group);                        
                    }

                    // Groupes
                    $this->writeln('');
                    $this->writeln('== GROUPES ==========================================');
                    $results = $this->ldap->search("type=Groupe", ['cn','description','gidNumber'], $this->ldap_basedn);
                    foreach($results as $result) {
                        $cn=$result["cn"];
                        $ldapfilter="(&(type=Groupe)(cn=$cn))";

                        $label="GROUPE - ".$result["cn"];
                        $this->writeln("    - $label");
                        if(!$simulate) $this->addmodGroup($label,$ldapfilter,$scribe_group);                        
                    }
                }
                elseif($ldap_template=="open") {
                    if($this->container->getParameter('openldapsynchrogroup')) {
                        $this->writeln('');
                        $this->writeln('== GROUPES ==========================================');

                        $results = $this->ldap->search($this->container->getParameter('openldapreqgroup'), ['cn','description','gidNumber'], $this->ldap_basegroup);
                        foreach($results as $result) {
                            $cn=$result["cn"];
                            $ldapfilter="(&".$this->container->getParameter('openldapreqgroup')."(cn=$cn))";
    
                            $label=$result["cn"];
                            $this->writeln("    - $label");
                            if(!$simulate) $this->addmodGroup($label,$ldapfilter,false);                        
                        }                        
                    }
                }

                $this->writeln('');
                $this->writeln('== USERS ============================================');
                
                // On stocke tout les email déjà existant
                $this->writeln('== Stocker les emails utilisateurs existants');
                $users=$this->em->createQueryBuilder()->select('table.email')->from('CadolesCoreBundle:User','table')->getQuery()->getArrayResult();
                foreach($users as $user) {
                    array_push($ldapmails,$user["email"]);
                }                

                // On parcours les niveaux 01 pour connaitre les filtres ldap associé
                $nbusers=0;
                $datas=$this->em->createQueryBuilder()->select('table')->from('CadolesCoreBundle:Niveau01','table')->where('table.ldapfilter IS NOT NULL')->getQuery()->getArrayResult();
                $tberrors=[];
                foreach($datas as $data) {
                    // On execute le filtre d'appartenance à ce niveau
                    $this->writeln("== Récupération des utilisateurs de l'annuaire");
                    $niveau01=$this->em->getRepository('CadolesCoreBundle:Niveau01')->find($data["id"]);
                    $results = $this->ldap->search($niveau01->getLdapfilter(), $fieldstoread, $this->ldap_baseuser);
                    $nbuserstotal=count($results);

                    // Pour chaque utilisateur ldap
                    $this->writeln('== Traitement des utilisateurs du niveau = '.$niveau01->getLabel(). " = ".$niveau01->getLdapfilter());
                    foreach($results as $result) {
                        // Niveau 01 en cours à récupérer car on clear à em à chaque $result
                        $niveau01=$this->em->getRepository('CadolesCoreBundle:Niveau01')->find($data["id"]);

                        // Compteur de users
                        $nbusers++;

                        // Formatage du résultat
                        if(is_array($result[$ldap_username])) {
                            $result[$ldap_username]=$result[$ldap_username][0];
                        }

                        $result[$ldap_username]=utf8_encode($result[$ldap_username]);
                        if(!isset($result[$ldap_lastname])) $result[$ldap_lastname] = "";
                        if(!isset($result[$ldap_firstname])) $result[$ldap_firstname] = "";

                        if(!array_key_exists($ldap_email,$result)||empty($result[$ldap_email])) {
                            $result[$ldap_email]=$result[$ldap_username]."@nomail.fr";
                        }
                        $result[$ldap_email]=strtolower($result[$ldap_email]);
                        $result[$ldap_email]=utf8_encode($result[$ldap_email]);

                        // On sauvegarde ce user
                        if(in_array($result[$ldap_username],$ldapusers)) {
                            $this->writelnred("    - Création dans Bundle impossible     >> ".$result[$ldap_username]." deux users avec le meme uid");
                            continue;
                        }
                        array_push($ldapusers,$result[$ldap_username]);
                        
                        // Création ou Modification du user
                        $user=$this->em->getRepository('CadolesCoreBundle:User')->findOneBy(array('username' => $result[$ldap_username]));
                        if(!$user) {
                            if(empty($result[$ldap_email]))
                                array_push($tberrors,"    - Création dans Bundle impossible         >> ".$result[$ldap_username]." sans email");
                            else {
                                if(in_array($result[$ldap_email],$ldapmails))
                                    array_push($tberrors,"    - Création dans Bundle impossible         >> ".$result[$ldap_username]." un autre utilisateur a déjà ce mail = ".$result[$ldap_email]);
                                else {
                                    array_push($ldapmails,$result[$ldap_email]);
                                    $this->writeln("    - Création dans Bundle     >> ".$result[$ldap_username]);
                                    if(!$simulate) $this->addUser($niveau01,$result[$ldap_username],$result[$ldap_firstname],$result[$ldap_lastname],$result[$ldap_email],$ldap_usersadmin);
                                }
                            }
                        }
                        else {
                            $toadmin=false;
                            if(in_array($result[$ldap_username],$ldap_usersadmin)&&!in_array("ROLE_ADMIN",$user->getRoles()))
                                $toadmin=true;
                
                            if($user->getLastname()!=$result[$ldap_lastname]||$user->getFirstname()!=$result[$ldap_firstname]||$user->getEmail()!=$result[$ldap_email]||$toadmin) {
                                $usermail=$this->em->getRepository('CadolesCoreBundle:User')->findOneBy(array('email' => $result[$ldap_email]));
                                
                                if($usermail&&$usermail!=$user) {
                                    array_push($tberrors,"    - Modification dans Bundle impossible     >> ".$result[$ldap_username]." un autre utilisateur a déjà ce mail = ".$result[$ldap_email]);
                                }
                                else {
                                    $this->writeln("    - Modification dans Bundle >> ".$result[$ldap_username]);
                                    if(!$simulate) $this->modUser($user,$result[$ldap_username],$result[$ldap_firstname],$result[$ldap_lastname],$result[$ldap_email],$ldap_usersadmin);
                                }
                            }
                        }

                        if(!$simulate) {
                            $this->em->clear();
                        }

                        if($nbusers%1000==0) $this->writeln("    == Nombre d'utilisateurs traités = $nbusers sur $nbuserstotal ==");
                    }
                }
                if(!$simulate) {
                    $this->writeln("    == Nombre d'utilisateurs traités = $nbusers sur $nbuserstotal ==");
                    $this->em->flush();
                    $this->em->clear();
                }

                foreach($tberrors as $error) {
                    $this->writelnred("    == ERROR == $error");
                }

                $this->writeln('');
                $this->writeln('== USERS GROUP ======================================');                

                $groups=$this->em->getRepository('CadolesCoreBundle:Group')->findAll();
                foreach($groups as $group) {
                    $ldapusersgroup=array();

                    $ldapfilter=$group->getLdapfilter();

                    $this->writeln('');
                    $this->writeln('== '.$group->getLabel());                
    
                    if(!is_null($ldapfilter)) {
                        $results = $this->ldap->search($ldapfilter,[$ldap_username,$ldap_member] , $this->ldap_basedn);

                        foreach($results as $result) {
                            

                            if(isset($result[$ldap_member])) {
                                // Si memberid est un tableau il y a plusieur user dedans
                                if(is_array($result[$ldap_member])) {
                                    foreach($result[$ldap_member] as $key => $value) {
                                        if(is_int($key)) {
                                            $username=$value;

                                            // si le username forme un DN, il faut récupérer juste la première entrée
                                            $tmp=explode(",",$username);
                                            if(is_array($tmp)&&count($tmp)>1) {
                                                $tmp=explode("=",$tmp[0]);
                                                $username=$tmp[1];
                                            }

                                            $user=$this->em->getRepository('CadolesCoreBundle:User')->findOneBy(array('username' => $username));
                                            if($user) {
                                                array_push($ldapusersgroup,$username);
                                                $this->writeln("    - Rattacher   >> ".$username);
                                                if(!$simulate) $this->addtoGroup($user,$group);
                                            }
                                        }
                                    }
                                }
                                // sinon m'a qu'un seul uid
                                else {
                                    $username=$result[$ldap_member];

                                    // si le username forme un DN, il faut récupérer juste la première entrée
                                    $tmp=explode(",",$username);
                                    if(is_array($tmp)&&count($tmp)>1) {
                                        $tmp=explode("=",$tmp[0]);
                                        $username=$tmp[1];
                                    }

                                    $user=$this->em->getRepository('CadolesCoreBundle:User')->findOneBy(array('username' => $username));
                                    if($user) {
                                        array_push($ldapusersgroup,$username);
                                        $this->writeln("    - Rattacher   >> ".$username);
                                        if(!$simulate) $this->addtoGroup($user,$group);
                                    }
                                }
                            }

                            if(isset($result[$ldap_username])) {
                                $user=$this->em->getRepository('CadolesCoreBundle:User')->findOneBy(array('username' => $result[$ldap_username]));
                                if($user) {
                                    array_push($ldapusersgroup,$result[$ldap_username]);
                                    $this->writeln("    - Rattacher   >> ".$result[$ldap_username]);
                                    if(!$simulate) $this->addtoGroup($user,$group);
                                }
                            }
                        }

                        $members=$this->em->getRepository('CadolesCoreBundle:UserGroup')->findBy(array('group' => $group));
                        foreach($members as $member) {
                            if(!in_array($member->getUser()->getUsername(),$ldapusersgroup)) {
                                $this->writeln("    - Détattacher >> ".$member->getUser()->getUsername());
                                if(!$simulate) {
                                    $this->em->remove($member);
                                    $this->em->flush();                            
                                }                                
                            }
                        }
                    }
                }
                

                $this->writeln('');
                $this->writeln('=====================================================');
                $this->writeln('== SYNCHONISATION BUNDLE TO LDAP ====================');
                $this->writeln('=====================================================');

                $this->writeln('');
                $this->writeln('== USERS ============================================');

                // Pour chaque utilisateur de la base
                //$users=$this->em->getRepository('CadolesCoreBundle:User')->findAll();
                $datas=$this->em->createQueryBuilder()->select('table.id,table.username')->from('CadolesCoreBundle:User','table')->getQuery()->getArrayResult();
                $nbusers=0;

                // tentative d'optimisation
                $flipped = array_flip($ldapusers);

                foreach($datas as $data) {
                    $nbusers++;

                    // Si l'utilisateur n'est pas dans la liste des users ldap : on le supprime
                    if(!isset($flipped[$data["username"]])) {
                        $user=$this->em->getRepository('CadolesCoreBundle:User')->find($data["id"]);
                        if($user->getUsername()=="admin")
                            $this->writeln("    - Ne jamais supprimer  >> ".$user->getUsername());
                        else {
                            $this->writeln("    - Suppression dans Bundle  >> ".$user->getUsername());
                            if(!$simulate) {
                                $this->em->remove($user);
                                $this->em->flush();
                                                         
                            }
                        }
                    }
                    else { 
                        //on peut unset les recherches suivantes seront plus rapide
                        unset($flipped[$data["username"]]);
                    }
                    
                    $this->em->clear();   
                    if($nbusers%1000==0) $this->writelnred("    == Nombre d'utilisateurs traités = $nbusers==");
                }

                $this->writeln('');
                $this->writeln('== GROUPS ============================================');
                // Pour chaque groupe annuaire on s'assure que le groupe existe bien dans l'annuaire
                $groups=$this->em->getRepository('CadolesCoreBundle:Group')->findBy(["fgtemplate"=>true]);
                foreach($groups as $group) {
                    if(stripos($group->getLabel(),"PROFIL - ")===false) {
                        $results = $this->ldap->search($group->getLdapfilter(), [], $this->ldap_basedn);
                        if(count($results)==0) {
                            $this->writeln("    - Suppression dans Bundle  >> ".$group->getLabel());
                            if(!$simulate) {
                                if($group->getFgcanshare()) {
                                    // Sur l'ensemble des pages liés
                                    $pages=$group->getPages();
                                    foreach($pages as $page) {
                                        $getgroups=$page->getGroups();
                                        // si la page est lié qu'à un seul group on peut la supprimer
                                        if($getgroups->count()==1)
                                            $this->em->remove($page);
                                    }
                    
                                    // Sur l'ensemble des calendar liés
                                    $calendars=$group->getCalendars();
                                    foreach($calendars as $calendar) {
                                        $getgroups=$calendar->getGroups();
                                        // si la page est lié qu'à un seul group on peut la supprimer
                                        if($getgroups->count()==1)
                                            $this->em->remove($calendar);
                                    }                
                    
                                    // Sur l'ensemble des blog liés
                                    $blogs=$group->getBlogs();
                                    foreach($blogs as $blog) {
                                        $getgroups=$blog->getGroups();
                                        // si la page est lié qu'à un seul group on peut la supprimer
                                        if($getgroups->count()==1)
                                            $this->em->remove($blog);
                                    }  
                                    
                                    // Sur l'ensemble des project liés
                                    $projects=$group->getProjects();
                                    foreach($projects as $project) {
                                        $getgroups=$project->getGroups();
                                        // si la page est lié qu'à un seul group on peut la supprimer
                                        if($getgroups->count()==1)
                                            $this->em->remove($project);
                                    }                  
                                }
                    
                                $this->em->remove($group);
                                $this->em->flush();
                            }
                        }
                    }
                }

            }
        }
        else {
            $this->writeln('');
            $this->writeln('=====================================================');
            $this->writeln('== SYNCHONISATION BUNDLE TO LDAP ====================');
            $this->writeln('=====================================================');

            $this->writeln('');
            $this->writeln('== NIVEAU01 =========================================');
            $baseNiveau01 = $this->container->getParameter('ldap_baseniveau01');

            $datas = $this->em
                    ->createQueryBuilder()
                    ->select('table')
                    ->from('CadolesCoreBundle:Niveau01','table')
                    ->getQuery()
                    ->getResult();
            foreach($datas as $data) {
                $criteria = '(cn='.$data->getLabel().')';
                $subbranch=$baseNiveau01;
                $results = $this->ldap->search($criteria, array('cn'), $subbranch);
    
                // Mise à jour si elle existe
                if(count($results) > 0) {
                    $this->writeln('    - Modification dans annuaire >> '.$data->getLabel());
                    if(!$simulate) $this->ldap->modifyNiveau01($data,$data->getLabel(),$results[0]["cn"]);
                }
                // Sinon création de la fiche
                else {
                    $this->writeln('    - Création dans annuaire     >> '.$data->getLabel());
                    if(!$simulate) $this->ldap->addNiveau01($data);
                }
            }            

            $this->writeln('');
            $this->writeln('== NIVEAU02 =========================================');
            $baseNiveau02 = $this->container->getParameter('ldap_baseniveau02');

            $datas = $this->em
                    ->createQueryBuilder()
                    ->select('table')
                    ->from('CadolesCoreBundle:Niveau02','table')
                    ->getQuery()
                    ->getResult();
            foreach($datas as $data) {
                $criteria = '(cn='.$data->getLabel().')';
                $subbranch=$baseNiveau02;
                $results = $this->ldap->search($criteria, array('cn'), $subbranch);
    
                // Mise à jour si elle existe
                if(count($results) > 0) {
                    $this->writeln('    - Modification dans annuaire >> '.$data->getLabel());
                    if(!$simulate) $this->ldap->modifyNiveau02($data,$data->getLabel(),$results[0]["cn"]);
                }
                // Sinon création de la fiche
                else {
                    $this->writeln('    - Création dans annuaire     >> '.$data->getLabel());
                    if(!$simulate) $this->ldap->addNiveau02($data);
                }
            }

            $this->writeln('');
            $this->writeln('== GROUP ============================================');
            $baseGroup = $this->container->getParameter('ldap_basegroup');

            $datas = $this->em
                    ->createQueryBuilder()
                    ->select('table')
                    ->from('CadolesCoreBundle:Group','table')
                    ->getQuery()
                    ->getResult();
            foreach($datas as $data) {
                $criteria = '(cn='.$data->getLabel().')';
                $subbranch=$baseGroup;
                $results = $this->ldap->search($criteria, array('cn'), $subbranch);
    
                // Mise à jour si elle existe
                if(count($results) > 0) {
                    $this->writeln('    - Modification dans annuaire >> '.$data->getLabel());
                    if(!$simulate) $this->ldap->modifyGroup($data,$data->getLabel(),$results[0]["cn"]);
                }
                // Sinon création de la fiche
                else {
                    $this->writeln('    - Création dans annuaire     >> '.$data->getLabel());
                    if(!$simulate) $this->ldap->addGroup($data);
                }
            }     

            $this->writeln('');
            $this->writeln('== USER =============================================');
            $baseUser = $this->container->getParameter('ldap_baseuser');

            $datas = $this->em
                    ->createQueryBuilder()
                    ->select('table')
                    ->from('CadolesCoreBundle:User','table')
                    ->getQuery()
                    ->getResult();
            foreach($datas as $data) {
                $criteria = '('.$ldap_username.'='.$data->getUsername().')';
                $subbranch=$baseUser;
                $results = $this->ldap->search($criteria, array($ldap_username), $subbranch);

                // S'assurer que SIREN correspond au Niveau01
                if($data->getNiveau01()->getSiren()!=$data->getSiren()) {
                    $data->SetSiren($data->getNiveau01()->getSiren());
                    $data->flush();
                }

                // S'assurer que SIRET correspond au Niveau02
                if($data->getNiveau02()!==null&&$data->getNiveau01()->getSiren()!=$data->getSiren()) {
                    $data->SetSiret($data->getNiveau02()->getSiret());
                    $data->flush();
                }
    
                // Mise à jour si elle existe
                if(count($results) > 0) {
                    $this->writeln('    - Modification dans annuaire >> '.$data->getUsername());
                    if(!$simulate) $this->ldap->modifyUser($data);
                }
                // Sinon création de la fiche
                else {
                    $this->writeln('    - Création dans annuaire     >> '.$data->getUsername());
                    if(!$simulate) $this->ldap->addUser($data);
                }

                // Rattachement à Niveau01 et Niveau02
                if(!$simulate) $this->ldap->addGroupUser($data);
            }   
            
            $this->writeln('');
            $this->writeln('== USER NIVEAU01 =======================================');
            $baseniveau01 = $this->container->getParameter('ldap_baseniveau01');

            $datas = $this->em
                    ->createQueryBuilder()
                    ->select('table')
                    ->from('CadolesCoreBundle:Niveau01','table')
                    ->getQuery()
                    ->getResult();
            foreach($datas as $data) {
                $criteria = '(cn='.$data->getLabel().')';
                $subbranch=$baseniveau01;
                $results = $this->ldap->search($criteria, array('cn'), $subbranch);
    
                // Mise à jour des membres du groupes
                if(count($results) > 0) {
                    $this->writeln('    - '.$data->getLabel());
                    $dn=$this->ldap->getNiveau01DN($data->getLabel());
                    $attrs["memberuid"]=array();
                    $attrs["cadolesMember"]=array();
                    if($ldap_type=="AD") $attrs["member"]=array();

                    foreach($data->getUsers() as $userniveau01) {
                        array_push($attrs["memberuid"],$userniveau01->getUsername());
                        array_push($attrs["cadolesMember"],$this->ldap->getUserDN($userniveau01));
                        if($ldap_type=="AD") array_push($attrs["member"],$this->ldap->getUserDN($userniveau01));

                        $this->writeln('        > '.$userniveau01->getUsername());
                    }
                    if(!$simulate) $this->ldap->ldapModify($dn, $attrs);
                }
            }

            $this->writeln('');
            $this->writeln('== USER NIVEAU02 =======================================');
            $baseniveau02 = $this->container->getParameter('ldap_baseniveau02');

            $datas = $this->em
                    ->createQueryBuilder()
                    ->select('table')
                    ->from('CadolesCoreBundle:Niveau02','table')
                    ->getQuery()
                    ->getResult();
            foreach($datas as $data) {
                $criteria = '(cn='.$data->getLabel().')';
                $subbranch=$baseniveau02;
                $results = $this->ldap->search($criteria, array('cn'), $subbranch);
    
                // Mise à jour des membres du groupes
                if(count($results) > 0) {
                    $this->writeln('    - '.$data->getLabel());
                    $dn=$this->ldap->getNiveau02DN($data->getLabel());
                    $attrs["memberuid"]=array();
                    $attrs["cadolesMember"]=array();
                    if($ldap_type=="AD") $attrs["member"]=array();

                    foreach($data->getUsers() as $userniveau01) {
                        array_push($attrs["memberuid"],$userniveau01->getUsername());
                        array_push($attrs["cadolesMember"],$this->ldap->getUserDN($userniveau01));
                        if($ldap_type=="AD") array_push($attrs["member"],$this->ldap->getUserDN($userniveau01));

                        $this->writeln('        > '.$userniveau01->getUsername());
                    }
                    if(!$simulate) $this->ldap->ldapModify($dn, $attrs);
                }
            }


            $this->writeln('');
            $this->writeln('== USER GROUP =======================================');
            $baseGroup = $this->container->getParameter('ldap_basegroup');

            $datas = $this->em
                    ->createQueryBuilder()
                    ->select('table')
                    ->from('CadolesCoreBundle:Group','table')
                    ->getQuery()
                    ->getResult();
            foreach($datas as $data) {
                $criteria = '(cn='.$data->getLabel().')';
                $subbranch=$baseGroup;
                $results = $this->ldap->search($criteria, array('cn'), $subbranch);
    
                // Mise à jour des membres du groupes
                if(count($results) > 0) {
                    $this->writeln('    - '.$data->getLabel());
                    $dn=$this->ldap->getGroupDN($data->getLabel());
                    $attrs["memberuid"]=array();
                    $attrs["cadolesMember"]=array();
                    if($ldap_type=="AD") $attrs['member']=array();

                    foreach($data->getUsers() as $usergroupe) {
                        if(!in_array($usergroupe->getUser()->getUsername(), $attrs["memberuid"])) {
                            array_push($attrs["memberuid"],$usergroupe->getUser()->getUsername());
                            array_push($attrs["cadolesMember"],$this->ldap->getUserDN($usergroupe->getUser()));
                            if($ldap_type=="AD") array_push($attrs["member"],$this->ldap->getUserDN($usergroupe->getUser()));

                            $this->writeln('        > '.$usergroupe->getUser()->getUsername());
                        }
                        else {
                            $this->writelnred('        > EXIST'.$usergroupe->getUser()->getUsername());
                        }
                    }
                    if(!$simulate) $this->ldap->ldapModify($dn, $attrs);
                }
            }

            $this->writeln('');
            $this->writeln('=====================================================');
            $this->writeln('== SYNCHONISATION LDAP TO BUNDLE ====================');
            $this->writeln('=====================================================');            


            $this->writeln('');
            $this->writeln('== NIVEAU01 =========================================');
            $baseNiveau01 = $this->container->getParameter('ldap_baseniveau01');

            $criteria = '(cn=*)';
            $subbranch=$baseNiveau01;
            $results = $this->ldap->search($criteria, array('cn'), $subbranch);
            foreach($results as $result) { 
                $data = $this->em->getRepository('CadolesCoreBundle:Niveau01')->findBy(array('label' => $result["cn"]));
                if($data) $this->writeln('    - Existe dans bundle         >> '.$result["cn"]);
                else {
                    $this->writeln('    - A supprimer dans annuaire  >> '.$result["cn"]);
                    $dn=$this->ldap->getNiveau01DN($result["cn"]);
                    if(!$simulate) $this->ldap->deleteByDN($dn);
                }
            }

            $this->writeln('');
            $this->writeln('== NIVEAU02 =========================================');
            $baseNiveau02 = $this->container->getParameter('ldap_baseniveau02');

            $criteria = '(cn=*)';
            $subbranch=$baseNiveau02;
            $results = $this->ldap->search($criteria, array('cn'), $subbranch);
            foreach($results as $result) { 
                $data = $this->em->getRepository('CadolesCoreBundle:Niveau02')->findBy(array('label' => $result["cn"]));
                if($data) $this->writeln('    - Existe dans bundle         >> '.$result["cn"]);
                else {
                    $this->writeln('    - A supprimer dans annuaire  >> '.$result["cn"]);
                    $dn=$this->ldap->getNiveau02DN($result["cn"]);
                    if(!$simulate) $this->ldap->deleteByDN($dn);
                }
            }            


            $this->writeln('');
            $this->writeln('== GROUP ============================================');
            $baseGroup = $this->container->getParameter('ldap_basegroup');

            $criteria = '(cn=*)';
            $subbranch=$baseGroup;
            $results = $this->ldap->search($criteria, array('cn'), $subbranch);
            foreach($results as $result) { 
                $data = $this->em->getRepository('CadolesCoreBundle:Group')->findBy(array('label' => $result["cn"]));
                if($data) $this->writeln('    - Existe dans bundle         >> '.$result["cn"]);
                else {
                    $this->writeln('    - A supprimer dans annuaire  >> '.$result["cn"]);
                    $dn=$this->ldap->getGroupDN($result["cn"]);
                    if(!$simulate) $this->ldap->deleteByDN($dn);
                }
            }   
            
            $this->writeln('');
            $this->writeln('== USER =============================================');
            $baseUser = $this->container->getParameter('ldap_baseuser');

            $criteria = '('.$ldap_username.'=*)';
            $subbranch=$baseUser;
            $results = $this->ldap->search($criteria, array($ldap_username), $subbranch);
            foreach($results as $result) { 
                $data = $this->em->getRepository('CadolesCoreBundle:User')->findBy(array('username' => $result[$ldap_username]));
                if($data) $this->writeln('    - Existe dans bundle         >> '.$result[$ldap_username]);
                else {
                    $this->writeln('    - A supprimer dans annuaire  >> '.$result[$ldap_username]);
                    $dn=$ldap_username.'='.$result[$ldap_username].','.$baseUser;
                    if(!$simulate) $this->ldap->deleteByDN($dn);
                }
            }             
        }

        $this->writeln('');
        return 1;
    }

    private function writelnred($string) { 
        $this->output->writeln('<fg=red>'.$string.'</>');
        $this->filesystem->appendToFile($this->rootlog.'cron.log', $string."\n");
    }
    private function writeln($string) { 
        $this->output->writeln($string);
        $this->filesystem->appendToFile($this->rootlog.'cron.log', $string."\n");
    }   

    protected function addmodGroup($label,$ldapfilter,$fgcanshare) {
        $portal_activate = $this->container->getParameter('portal_activate');
        $group=$this->em->getRepository('CadolesCoreBundle:Group')->findOneBy(array('fgtemplate' => false, 'label' => $label));
        if($group) {
            $this->writelnred("    - ".$label." existe déjà comme groupe interne à Ninegate");
            return 0;
        }

        $group=$this->em->getRepository('CadolesCoreBundle:Group')->findOneBy(array('fgtemplate' => true, 'label' => $label));
        if(!$group) {
            $group=new Group();
            $group->setFgcancreatepage(false);
            $group->setFgcancreateblog(false);
            $group->setFgcancreatecalendar(false);
            $group->setFgcancreateproject(false);            
        }

        $group->setFgcanshare($fgcanshare);
        $group->setLabel($label);
        $group->setFgopen(false);
        $group->setFgall(false);
        $group->setLdapfilter($ldapfilter);
        $group->setFgtemplate(true);
        
        if($portal_activate) {
            $pagetemplate=$this->em->getRepository("CadolesPortalBundle:Page")->find(-110);
            if($pagetemplate) $group->setPagetemplate($pagetemplate);
        }

        $this->em->persist($group);
        $this->em->flush();      
      
        if($fgcanshare && $portal_activate) {
            // On regarde s'il a au moins une page
            if($group->getPages()->isEmpty()) {
                $page=$this->em->getRepository("CadolesPortalBundle:Page")->clonePage(null,$group->getPagetemplate());
                $group->addPage($page);
                $page->setName($group->getLabel());

                $this->em->persist($page);
                $this->em->persist($group);
                $this->em->flush();   
            }

            // On regarde s'il a au moins un calendrier
            if($group->getCalendars()->isEmpty()) {
                $calendar=new Calendar();
                $key = Uuid::uuid4();

                $calendar->setName($group->getLabel());
                $calendar->setKeyvalue($key);                
                $calendar->addGroup($group);
                $calendar->setColor($group->getColor());
                $calendar->setType(0);

                $this->em->persist($calendar);
                $this->em->flush();                  
            }

            // On regarde s'il a au moins un blog
            if($group->getBlogs()->isEmpty()) {
                $blog=new Blog();

                $blog->setName($group->getLabel());
                $blog->addGroup($group);

                $this->em->persist($blog);
                $this->em->flush();                  
            } 
            
            // On regarde s'il a au moins un project
            if($group->getProjects()->isEmpty()) {
                $project=new Project();

                $project->setName($group->getLabel());
                $project->addGroup($group);

                $this->em->persist($project);
                $this->em->flush();                  
            }             
        }        
    }

    protected function addtoGroup($user,$group) {
        $member=$this->em->getRepository('CadolesCoreBundle:UserGroup')->findOneBy(array('group' => $group, 'user' => $user));
        if(!$member) {
            $member= new UserGroup();
            $member->setGroup($group);
            $member->setUser($user);
            $member->setRolegroup(0);
        }  
        
        // Si modèle scribe 
        $ldap_template = $this->container->getParameter('ldap_template');
        $scribe_master = $this->container->getParameter('scribe_master');
        if($ldap_template=="scribe"&&$scribe_master) {
            $ldapfilter="(|(&(uid=".$user->getUsername().")(ENTPersonProfils=enseignant))(&(uid=".$user->getUsername().")(typeadmin=0))(&(uid=".$user->getUsername().")(typeadmin=2)))";
            $results = $this->ldap->search($ldapfilter, ['uid'], $this->ldap_basedn);
            if($results) $member->setRolegroup(50);
        }

        $this->em->persist($member);
        $this->em->flush();    
    }

    protected function addUser($niveau01,$username,$firstname,$lastname,$email,$usersadmin) {
        $user = new User();

        $user->setUsername($username);
        $user->setLastname($lastname);
        $user->setFirstname($firstname);
        $user->setEmail($email);        
        $user->setNiveau01($niveau01);
        $user->setSiren($niveau01->getSiren());
        $user->setPassword("PASSWORDFROMEXTERNE");
        $user->setVisible(true);
        $user->setAuthlevel("simple");
        $user->setBelongingpopulation("agent");

        if(in_array($username,$usersadmin))
            $user->setRole("ROLE_ADMIN");
        else  {
            $user->setRole("ROLE_USER");

            // Si modèle scribe 
            $ldap_template = $this->container->getParameter('ldap_template');
            if($ldap_template=="scribe") {
                $ldapfilter="(|(&(uid=".$user->getUsername().")(ENTPersonProfils=enseignant))(&(uid=".$user->getUsername().")(typeadmin=0))(&(uid=".$user->getUsername().")(typeadmin=2)))";
                $results = $this->ldap->search($ldapfilter, ['uid'], $this->ldap_basedn);
                if($results) $user->setRole("ROLE_ANIM");
            }       
        }     

        $this->em->persist($user);
        $this->em->flush();
    }

    protected function modUser($user,$username,$firstname,$lastname,$email,$usersadmin) {
        $user->setLastname($lastname);
        $user->setFirstname($firstname);
        $user->setEmail($email);

        if(in_array($username,$usersadmin))
            $user->setRole("ROLE_ADMIN");

        $this->em->persist($user);
        $this->em->flush();
    }

}
