<?php
//$Id$
//gen openMairie le 16/12/2020 17:03

require_once "../gen/obj/plan_election.class.php";

class plan_election extends plan_election_gen {

    /**
     * Definition des actions disponibles sur la classe
     *
     * @return void
     */
    function init_class_actions() {
        parent::init_class_actions();

        // suppression et ajout disponible que si l'élection est à l'étape du
        // paramétrage
        $this->class_actions[2]["condition"][1] = 'is_parametrage_or_simulation';
        $this->class_actions[1]["condition"][1] = 'is_parametrage_or_simulation';

        // ACTION - 20 - parametrage_election_plan
        $this->class_actions[20] = array(
            "identifier" => "parametrage_election_plan",
            "portlet" => array(
                "type" => "action-direct-with-confirmation",
                "libelle" => _("Mettre à jour le parametrage des plans"),
                "order" => 200,
                "class" => "edit-16",
            ),
            "view" => "formulaire",
            "method" => "maj_parametrage_plans",
            "button" => "diffuser",
            "permission_suffix" => "maj_parametrage_plans",
            "condition" => array(
                'pas_etape_saisie',
                'pas_etape_finalisation',
                'non_archivee'
            )
        );
    }

    /**
     * Utiliser l'action 'modifier' du formulaire liant un plan à l'élection
     * permet de faire une nouvelle récupération du parametrage du plan.
     * Pour mettre à jour le paramétrage des plans de l'élection, il
     * suffit donc d'utiliser l'action de modification pour chaque
     * plan_election de l'élection.
     * Pour simuler cette utilisationl la méthode triggermodifier est utilisés
     * sur chaque instance de plan_election lié à l'élection.
     *
     * @return boolean indique si le traitement à fonctionné ou pas
     */
    protected function maj_parametrage_plans() {
        // Il faut d'abord récupérer la liste des plans de l'élection.
        $plansElection = $this->get_liste_plans_election($this->getVal('election'));
        // Ensuite les plans liés à chacune des centaines sont ajoutés à la liste
        // pour être également mis à jour
        $election = $this->f->get_element_by_id('election', $this->getVal('election'));
        $centaines = $election->get_centaines_election();
        foreach ($centaines as $centaine) {
            $plansCentaine = $this->get_liste_plans_election($centaine->getVal('election'));
            $plansElection = array_merge($plansElection, $plansCentaine);
        }
        foreach ($plansElection as $planElection) {
            // Le tableau de valeur passé en paramétre du triggermodifier contiens
            // les valeurs enregistrés dans le plan_election pour éviter de modifier
            // l'enregistrement (seul les paramétres du plan doivent être mis à jour)
            $idplanElection = $planElection->getVal('plan_election');
            $valplanElection = array();
            foreach ($planElection->champs as $champ) {
                $valplanElection[$champ] = $planElection->getVal($champ);
            }
            $dnu1 = null;
            $dnu2 = null;
            $planElection->triggermodifier($idplanElection, $dnu1, $valplanElection, $dnu2);
        }
        // Return true permet d'avoir un message de validation et false un message d'erreur
        $this->addToMessage('Paramétrage des plans mis à jour');
        return true;
    }

    /**
     * TRIGGER - triggerajouter.
     *
     * @param string $id
     * @param null &$dnu1 @deprecated  Ne pas utiliser.
     * @param array $val Tableau des valeurs brutes.
     * @param null $dnu2 @deprecated  Ne pas utiliser.
     *
     * @return boolean
     */
    function triggerajouterapres($id, &$dnu1 = null, $val = array(), $dnu2 = null) {
        // Envoi de l'image du plan dans le repertoire web/res/idelection/plan
        $this->envoi_images_web($val['plan'], $val['election']);
        // Ecriture du fichier plans.json
        $this->ecris_json_plans_election($id, $val['election'], $val['plan']);
    }

    /**
     * TRIGGER - triggermodifier.
     *
     * @param string $id
     * @param null &$dnu1 @deprecated  Ne pas utiliser.
     * @param array $val Tableau des valeurs brutes.
     * @param null $dnu2 @deprecated  Ne pas utiliser.
     *
     * @return boolean
     */
    function triggermodifier($id, &$dnu1 = null, $val = array(), $dnu2 = null) {
        // Envoi de l'image du plan dans le repertoire web/res/idelection/plan
        $this->envoi_images_web($val['plan'], $val['election']);
        // Ecriture du fichier plans.json
        $this->ecris_json_plans_election($id, $val['election'], $val['plan']);
    }

    /**
     * TRIGGER - triggersupprimerapres.
     *
     * @param string $id
     * @param null &$dnu1 @deprecated  Ne pas utiliser.
     * @param array $val Tableau des valeurs brutes.
     * @param null $dnu2 @deprecated  Ne pas utiliser.
     *
     * @return boolean
     */
    function triggersupprimer($id, &$dnu1 = null, $val = array(), $dnu2 = null) {
        // Cherche tous les fichier ayant comme nom l'identifiant du plan et les supprime
        // Les plans ayant comme nom leur identifiant, le plan et les informations sont donc
        // mis à jour
        $election = $this->f->get_element_by_id('election', $this->getVal('election'));
        $path = $election->get_election_web_path();
        $supprimer = $this->f->rrmdir($path.'/plan_'.$this->getVal('plan'));
        $message = $supprimer ? 'Le dossier du plan est supprimé<br>' :
            'Echec de la suppression des plans<br>';
        // Met à jour les informations envoyées à la page web
        $infosPlans = $this->ecris_json_plans_election(
            $id,
            $this->getVal('election'),
            $this->getVal('plan'),
            true
        );
        $message .= $infosPlans ? 'Mise à jour du fichier plans.json' :
                'Erreur lors de la mise à jour du fichier';
        $this->addToMessage($message);
    }

    /**
     * Indique si l'élection est à l'étape du paramétrage ou pas
     *
     * @return boolean
     */
    protected function is_parametrage_or_simulation() {
        //Rcéupère l'election et verifie si elle est verrouillée ou pas
        $election = $this->f->get_element_by_id('election', $this->getVal('election'));
        return $election->is_etape_parametrage() || $election->is_etape_simulation();
    }

    /**
     * Récupère une instance de plan. A partir de cette instance
     * récupère l'uid de l'image du plan.
     * Cet uid permet ensuite de copier l'image du plan dans le repertoire web.
     * De la même manière les icones par défaut sont également copier dans le repertoire.
     *
     * La liste des plan_unites liés au plan est ensuite récupéré. A partir de cette
     * liste les icones choisies pour representer chaque unité du plan sont copiées
     * dans le repertoire du plan.
     *
     * @param integer $planId identfiant du plan dont on veut envoyer l'image
     * @param integer $election identifiant de l'élection pour savoir dans quel
     * repertoire envoyer l'image
     * @return boolean true : fichier ecris avec succes, false : erreurs
     */
    public function envoi_images_web($planId, $electionId) {
        $succes = false;
        if (! empty($planId) && ! empty($electionId)) {
            // Récupération de l'image du plan qui se trouve dans la
            //classe plan. Il faut donc commencer par récupérer une instance
            //de plan
            $election = $this->f->get_element_by_id('election', $electionId);
            $path = $election->get_election_web_path();
            if (! file_exists($path)) {
                if (! mkdir($path)) {
                    $this->addToMessage('repertoire web de l\'élection non crée');
                }
                // Puisque le répertoire n'existait pas, il est donc vide et l'élection va être
                // affiché "NC" dans le listing des élections du portail web.
                // Pour éviter ça, le fichier contenant les informations (dont le nom)
                // de l'élection est envoyé en même temps.
                // Pour éviter de dupliquer du la méthode d'écriture de ce fichier
                // issue de la classe election_unite est réutilisée. Cependant cette méthode utilise
                // des informations issues du formulaire de saisie de l'election_unite. Ces
                // informations sont donc récrées à la main pour pouvoir utiliser cette méthode
                // sans erreur
                $electionUnite = $this->f->get_element_by_id('election_unite', ']');
                $val = array(
                    'election_unite' => 0,
                    'election' => $electionId,
                    'envoi_web' => false
                );
                if (! $electionUnite->ecris_fichier_info_election_web($val)) {
                    $this->addToMessage('Les informations de l\'élection n\'ont pas été envoyé au portail web');
                }
            }
            $plan = $this->f->get_element_by_id('plan', $planId);
            $urlRepPlan = $path.'/plan_'.$plan->getVal('plan');
            // Le repertoire du plan est vidé pour s'assurer que les anciens plans
            // et icones n'existent plus
            if (file_exists($urlRepPlan)) {
                $this->f->rrmdir($urlRepPlan);
            }

            // Copie du plan dans le repertoire web
            if (! empty($plan->getVal('image_plan'))) {
                $uid = $plan->getVal('image_plan');
                $succes = $this->f->copier_fichier_du_filestorage(
                    $uid,
                    $urlRepPlan,
                    'plan'
                );
                if (! $succes) {
                    $this->addToMessage('Erreur lors de la copie du plan');
                    return $succes;
                }
            }

            // Copie des icones par défaut dans le repertoire du plan
            $icones = array('img_unite_arrivee', 'img_unite_non_arrivee');
            foreach ($icones as $icone) {
                if (! empty($plan->getVal($icone))) {
                    $uid = $plan->getVal($icone);
                    $succes = $this->f->copier_fichier_du_filestorage(
                        $uid,
                        $urlRepPlan,
                        $icone
                    );
                    if (! $succes) {
                        $this->addToMessage('Erreur lors de la copie des icones par défaut');
                        return $succes;
                    }
                }
            }

            // Récupération du paramétrage des unités lié au plan et copie
            // des icones choisie
            $plansUnite = $plan->get_liste_plan_unite();
            foreach ($plansUnite as $planUnite) {
                foreach ($icones as $icone) {
                    if (! empty($planUnite->getVal($icone))) {
                        $uid = $planUnite->getVal($icone);
                        $succes = $this->f->copier_fichier_du_filestorage(
                            $uid,
                            $urlRepPlan.'/'.$planUnite->getVal('plan_unite'),
                            $icone
                        );
                        if (! $succes) {
                            $this->addToMessage('Erreur lors de la copie des icones');
                            return $succes;
                        }
                    }
                }
            }
        }
        return $succes;
    }

    /**
     * Récupére le tableau du paramétrage des plans de l'élection.
     * Supprime la ligne correspondant à l'instance de plan_election.
     *
     * Si le paramétre supprimer vaut 'false' ajoute une case dans le tableau
     * contenant les informations du plan et des plan_unite qui lui sont associé.
     * Sinon le traitement s'arrête aprés suppression de la case du tableau.
     * Ainsi les paramétres de l'instance sont mis à jour dans le tableau sans
     * touché ceux des autres instances.
     *
     * Pour les champs correspondant à des images, les informations suivantes sont récupérées :
     *  - metadata
     *  - emplacement du fichier
     * Remarque : l'emplacement du fichier sert à remplacer le stockage de son contenu dans le
     * json. En effet, copier le contenu du fichier dans le tableau pose problème lors du
     * passage en json. Ainsi, pour que le contenu soit toujours accessible c'est le path
     * du fichier qui est donné.
     *
     * Enfin, un fichier json contenant le paramétrage est écris dans le répertoire
     * web de l'élection
     *
     * @param integer $electionId id de l'election
     * @param integer $planId identifiat du plan dont on doit récuperer le paramétrage
     * @param boolean $supprimer indique si les informations de l'instance doivent
     * être supprimée ou mise à jour
     * @return boolean indique si le fichier a bien été écris
     */
    public function ecris_json_plans_election($planElectionId, $electionId, $planId, $supprimer = false) {
        $succes = false;
        $images = array('img_unite_arrivee', 'img_unite_non_arrivee', 'image_plan');
        $parametrage = array();
        if (! empty($electionId) && ! empty($planElectionId)) {
            $election = $this->f->get_element_by_id('election', $electionId);
            $path = $election->get_election_web_path();
            $repertoire = $path.'/plan_'.$planId;
            // Récupération du tableau de paramétrage des plans de l'élection
            // Ce tableau est indexé avec les identifiants des plan_election.
            // Cela permet de modifier uniquement le plan_election concerné
            // sans toucher aux autres.
            // Si ce plan_election n'existe pas une case est ajouté, si il existe
            // seul sa case sera modifié.
            $parametrage = $election->get_parametrage_plans();
            unset($parametrage[$planElectionId]);

            if ($supprimer === false && ! empty($planId)) {

                // Récupération du plan et de la liste des plan_unite qui lui
                // sont associé
                $plan = $this->f->get_element_by_id('plan', $planId);
                $plansUnite = $plan->get_liste_plan_unite();

                // Stockage des valeurs de chaque champ de plan dans un tableau
                foreach ($plan->champs as $id => $champs) {
                    $parametrage[$planElectionId][$champs] = $plan->val[$id];
                    if (in_array($champs, $images) && ! empty($plan->val[$id])) {
                        $infoImage = $this->f->storage->get($plan->val[$id]);
                        // Enregistre toutes les infos nécessaire du fichier :
                        // les metadatas et l'emplacement de l'image
                        $extension = $this->f->get_extension($infoImage['metadata']);
                        $filepath = $repertoire.'/'.$champs.'.'.$extension;
                        if ($champs === 'image_plan') {
                            $filepath = $repertoire.'/plan.'.$extension;
                        }
                        $parametrage[$planElectionId][$champs] = array(
                            'filepath' => $filepath
                        );
                    }
                }
                
                // Stockage des valeurs de champs de chaque plan_unite associé
                foreach ($plansUnite as $planUnite) {
                    //Récupération du paramétrage de chaque lien entre le plan et des unités
                    $paramsPlansUnite = array();
                    foreach ($planUnite->champs as $id => $champs) {
                        $paramsPlansUnite[$champs] = $planUnite->val[$id];
                        
                        if (in_array($champs, $images) && ! empty($planUnite->val[$id])) {
                            $infoImage = $this->f->storage->get($planUnite->val[$id]);
                            $extension = $this->f->get_extension($infoImage['metadata']);
                            $paramsPlansUnite[$champs] = array(
                                'filepath' => $repertoire.'/'.
                                    $planUnite->getVal('plan_unite').
                                    '/'.$champs.'.'.$extension
                            );
                        }
                    }
                    $parametrage[$planElectionId]['plans_unite'][] = $paramsPlansUnite;
                }
            }

            // Ecriture du fichier json dans le repertoire de l'élection
            $plans = json_encode($parametrage);
            $succes = $this->f->write_file($path.'/plans.json', $plans);
        }
        return $succes;
    }

    /**
     * Fait une requête permettant de récupérer la liste de
     * tous les id des plans associé à l'élection.
     *
     * @param integer $electionId id de l'election dont on souhaite récupérer
     * les plans
     * @return array liste d'instance de plan_election
     */
    public function get_liste_plans_election($electionId) {
        // Requete permettant de récupérer les id de tous les plans de l'élection
        $plansElection = $this->f->simple_query('plan_election', 'plan_election', 'election', $electionId);
        // Stockage dans un tableau des instances de chaque lien plan - election à partir
        // des id récupérés
        $listePlans = array();
        foreach ($plansElection as $planElectionId) {
            $planElection = $this->f->get_element_by_id('plan_election', $planElectionId);
            $listePlans[] = $planElection;
        }
        return $listePlans;
    }

    /**
     * Pour un plan donné, récupère la liste des unités qui lui sont
     * associées. Remplis et retourne un tableau contenant pour chaque unité leur
     * position sur le plan (x et y).
     *
     * @param integer idPlan identifiant du plan
     * @return array liste des unités et de leur position sur le plan
     */
    protected function get_position_unites_plan($idPlan) {
        $positionUnites = array();
        $sql = 'SELECT
                    unite, position_x, position_y
                FROM
                    '.DB_PREFIXE.'plan_unite
                WHERE
                    plan = '.$idPlan;
        $res = $this->db->query($sql);
        // En cas d'erreur un tableau vide est renvoyé et un messsage d'erreur
        // est affiché
        if ($this->f->is_database_error(
            $sql,
            $res,
            'Erreur lors de la récupération de la position des unités sur le plan'
        )) {
            return $positionUnites;
        }

        while ($row = $res->fetchRow(DB_FETCHMODE_ASSOC)) {
            $positionUnites[$row['unite']]['positionx'] = $row['position_x'];
            $positionUnites[$row['unite']]['positiony'] = $row['position_y'];
        }

        return $positionUnites;
    }

     /**
     * SETTER FORM - setType.
     *
     * @param formulaire $form Instance formulaire.
     * @param integer $maj Identifant numérique de l'action.
     *
     * @return void
     */
    function setType(&$form, $maj) {
        parent::setType($form, $maj);
        // Pour les actions appelée en POST en Ajax, il est nécessaire de
        // qualifier le type de chaque champs (Si le champ n'est pas défini un
        // PHP Notice:  Undefined index dans core/om_formulaire.class.php est
        // levé). On sélectionne donc les actions de portlet de type
        // action-direct ou assimilé et les actions spécifiques avec le même
        // comportement.
        if ($this->get_action_param($maj, "portlet_type") == "action-direct"
            || $this->get_action_param($maj, "portlet_type") == "action-direct-with-confirmation") {
            //
            foreach ($this->champs as $value) {
                $form->setType($value, 'hidden');
            }
            $form->setType($this->clePrimaire, "hiddenstatic");
        }
        if ($maj == '0') {
            $form->setType('election', 'select');
        }
    }

    /**
     *
     * @return string
     */
    function get_var_sql_forminc__sql_election() {
        // Evite une erreur de BD, hors contexte de l'élection
        $sql = sprintf(
            "SELECT
                election.election, election.libelle
            FROM
                %selection
            ORDER BY
                election.libelle ASC",
            DB_PREFIXE
        );

        if ($this->is_in_context_of_foreign_key("election", $this->retourformulaire)) {
            $idElection = $this->f->get_submitted_get_value('idxformulaire');
            $sql = sprintf(
                "SELECT
                    election.election, election.libelle
                FROM
                    %selection
                WHERE
                    election = %d OR
                    election_reference = %d
                ORDER BY
                    election.libelle ASC",
                DB_PREFIXE,
                $idElection,
                $idElection
            );
        }
        return $sql;
    }
}
