<?php
//$Id$
//gen openMairie le 05/06/2019 12:14

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

class election_candidat extends election_candidat_gen {

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

        // Modification sont possible à toutes les étapes sauf celle de l'archivage
        $this->class_actions[1]["condition"][1] = 'election_non_archivee';
        // suppression disponible que si l'élection est à l'étape du paramétrage ou
        // de la simulation
        $this->class_actions[2]["condition"][1] = 'is_parametrage_or_simulation';
    }

    /**
     * TRIGGER - triggerajouterapres.
     *
     * Crée le lien entre le candidat et les unités (election_resultat) du candidat
     * suite à sa création.
     *
     * Ajoute un candidat à chaque centaine de l'élection avec le même paramétrage
     * que le candidat ajouté. Ainsi l'élection et les centaines ont toujours le
     * même paramétrage
     *
     * @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) {
        // Création des résultats des candidats
        $succes = $this->insert_election_resultat($val['election'], $id);

        // Ajout du candidat à chaque centaine
        $election = $this->f->get_element_by_id('election', $val['election']);
        $isCentaine = $this->f->boolean_string_to_boolean($election->getVal('is_centaine'));
        if (! $isCentaine) {
            $centaines = $election->get_centaines_election();
            foreach ($centaines as $centaine) {
                $valCentaine = $val;
                $valCentaine['election'] = $centaine->getVal('election');
                $valCentaine['photo'] = null;
                $ajout = $this->f->ajouter_element_BD('election_candidat', $valCentaine);
                if (! $ajout) {
                    $this->addToMessage(
                        'Le candidat n\'a pas été ajouté à la centaine ('
                        .$centaine->getVal('libelle').')'
                    );
                }
                $succes = $succes && $ajout;
            }
        }
        return $succes;
    }

    /**
     * TRIGGER - triggermodifierapres.
     *
     * Met à jour le paramétrage des candidats pour les centaines de l'élection.
     * Ainsi le paramétrage des candidats de l'élection et de ses centaines est
     * toujours le même
     *
     * @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 triggermodifierapres($id, &$dnu1 = null, $val = array(), $dnu2 = null) {
        // Maj des candidats pour chaque centaine
        $succes = $this->maj_parametrage_candidat_centaines($val);
        // Maj des photos des candidats de l'élection sur l'animation
        if (file_exists('../aff/res/'.$this->getVal('election').'/candidats.json')) {
            $animation = $this->f->get_element_by_id('animation', ']');
            $maj = $animation->envoi_infos_candidats_affichage($this->getVal('election'));
            $message = $maj ?
                'Les informations et les photos des candidats ont été mis à jour sur les animations' :
                'Attention : Les informations et les photos des candidats n\'ont pas été mis à jour sur les animations';
            $this->addToMessage($message);
            $succes = $succes && $maj;
        }
        return $succes;
    }

    /**
     * Récupère l'élection liée au candidat, puis récupére la liste des
     * centaines associées à cette élection.
     * Ensuite, met à jour le paramétrage du candidat correspondant, pour
     * chaque centaine, avec les valeurs issues du formulaire de modification
     * du candidat de l'élection.
     *
     * @param array $val tableau des valeurs issus du formulaire
     * @return boolean indique si la mise à jour à réussie
     */
    protected function maj_parametrage_candidat_centaines($val) {
        $succes = true;
        $election = $this->f->get_element_by_id('election', $val['election']);
        $centaines = $election->get_centaines_election();
        foreach ($centaines as $centaine) {
            $modification = false;
            $candidat = $this->get_election_candidat(
                $centaine->getVal('election'),
                $this->getVal('candidat')
            );

            // Prépare le tableau des valeur pour la modification. Ce tableau est
            // le même que celui issu du formulaire sauf que le champs élection
            // doit correspondre à l'id de la centaine
            foreach ($val as $champ => $valeur) {
                $val[$champ] = $valeur != '' ? $valeur : null;
            }
            $valCentaine = $val;
            $valCentaine['election_candidat'] = $candidat->getVal('election_candidat');
            $valCentaine['election'] = $centaine->getVal('election');
            $valCentaine['photo'] = null;

            if ($candidat != false) {
                $modification = $this->f->modifier_element_BD_by_id(
                    'election_candidat',
                    $candidat->getVal('election_candidat'),
                    $valCentaine
                );
            }
            if (! $modification) {
                $this->addToMessage(
                    'Le candidat n\'a pas été mis à jour pour la centaine ('
                    .$centaine->getVal('libelle').')'
                );
            }

            // Maj des photos des candidats de l'élection sur l'animation
            // Si il s'agit d'une centaine ce sont les informations de l'élection de référence qui
            // sont envoyées à l'affichage
            // Permet de mettre à jour les photos
            if (file_exists('../aff/res/'.$centaine->getVal('election').'/candidats.json')) {
                $animation = $this->f->get_element_by_id('animation', ']');
                $maj = $animation->envoi_infos_candidats_affichage(
                    $centaine->getVal('election_reference'),
                    $centaine->getVal('election')
                );
                $message = $maj ?
                    'Les informations et les photos des candidats ont été mis à jour sur les animations' :
                    'Attention : Les informations et les photos des candidats n\'ont pas été mis à jour sur les animations';
                $this->addToMessage($message);
                $succes = $succes && $maj;
            }

            $succes = $succes && $modification;
        }
        return $succes;
    }

    /**
     * Methode clesecondaire
     * Cette méthode sert à vérifier qu'il n'existe pas d'éléments d'autres table
     * qui référence election_candidat que l'on cherche à supprimer.
     * Cependant, cette méthode est appellée avant le traitement de la suppression
     * et notamment des triggers. Elle empêche donc la suppression en cascade du candidat
     * et des ses résultats.
     * Pour régler ce problème, cette méthode a donc du être surchargée et la vérification
     * de la présence d'élément référencant l'objet à supprimer dans la table
     * election_resultat a été supprimé. Ainsi, il est possible dans triggersupprimer() de
     * supprimer les résultats, puis vérifier qu'il n'existe pas/plus de référence dans
     * la table election_resultat avant de supprimer le candidat.
     */
    function cleSecondaire($id, &$dnu1 = null, $val = array(), $dnu2 = null) {
        //
    }

    /**
     * TRIGGER - triggersupprimer.
     *
     * Supprime les liens entre le candidat et les unités de l'élection (election_resultat)
     *
     * Supprime le candidat de chaque centaine de l'élection. Ainsi le paramétrage des
     * candidats de l'élection et de ses centaines est toujours le même
     *
     * @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) {
        $succes = $this->supprimer_resultats_candidat();
        // Vérifie si il reste des références au candidat dans la table election_resultat
        $this->rechercheTable($this->f->db, "election_resultat", "election_candidat", $id);
        
        // Suppression du candidat pour chaque centaine
        $election = $this->f->get_element_by_id('election', $this->getVal('election'));
        $centaines = $election->get_centaines_election();
        foreach ($centaines as $centaine) {
            $supression = false;
            $candidat = $this->get_election_candidat(
                $centaine->getVal('election'),
                $this->getVal('candidat')
            );

            if ($candidat != false) {
                $supression = $this->f->supprimer_element_BD($candidat);
            }

            if (! $supression) {
                $this->addToMessage(
                    'Le candidat n\'a pas été supprimé de la centaine ('
                    .$centaine->getVal('libelle').')'
                );
            }
        }

        $this->correct = $succes;
        return $this->correct;
    }

    /**
     * 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 $key => $value) {
                $form->setType($value, 'hidden');
            }
            $form->setType($this->clePrimaire, "hiddenstatic");
        }
        //L'élection ne doit pas être modifiable
        $form->setType('election', "selecthiddenstatic");
        //changement du type du champ photo pour pouvoir récupérer
        //une image lors de l'ajout ou de la modif d'un candidat et
        //pouvoir visualiser et/ou télécharger l'image en consultation
        //et en suppression
        if ($maj < 2) {
            $form->setType('couleur', 'hexa');
        }

        if ($maj==0) {
            $form->setType('siege', "hiddenstatic");
            $form->setType('siege_com', "hiddenstatic");
            $form->setType('siege_mep', "hiddenstatic");
        }

        // Définition aux différentes étapes du workflow de la liste des champs
        // pouvant être utilisé. Tous les champs du formulaire sont ensuite rendu
        // static sauf les champs de la liste
        if ($maj == 1) {
            $election = $this->f->get_element_by_id('election', $this->getVal('election'));
            $champsUtilisable = array();
            switch ($election->getVal('workflow')) {
                case 'Paramétrage':
                    $champsUtilisable = array(
                        'candidat',
                        'ordre',
                        'prefecture',
                        'age_moyen',
                        'age_moyen_com',
                        'age_moyen_mep',
                        'photo',
                        'couleur',
                        'parti_politique'
                    );
                    break;
                case 'Simulation':
                    $champsUtilisable = $this->champs;
                    break;
                case 'Saisie':
                    $champsUtilisable = array(
                        'photo',
                        'couleur'
                    );
                    break;
                case 'Finalisation':
                    $champsUtilisable = array(
                        'photo',
                        'couleur',
                        'siege',
                        'age_moyen',
                        'siege_com',
                        'age_moyen_com',
                        'siege_mep',
                        'age_moyen_mep'
                    );
                    break;
                default:
                    $champsUtilisable = array();
                    break;
            }

            foreach ($this->champs as $key => $value) {
                if (! in_array($value, $champsUtilisable)) {
                    $form->setType($value, 'hiddenstatic');
                }
            }
        }
    }

    /**
     * SETTER FORM - set_form_default_values
     * 
     * @param formulaire $form Instance formulaire.
     * @param integer $maj Identifant numérique de l'action.
     * @param integer $validation Marqueur de validation du formulaire.
     * 
     * @return void
     */
    function set_form_default_values(&$form, $maj, $validation) {
        // calcul du dernier + 1 numero d'ordre des candidats dans l'election
        if ($validation == 0 and $maj == 0) {
            if ($this->is_in_context_of_foreign_key('election', $this->retourformulaire)) {
                if (! empty($this->f->get_submitted_get_value('idxformulaire'))) {
                    $sql = sprintf(
                        "SELECT MAX(ordre)
                        FROM %selection_candidat
                        WHERE election = %d",
                        DB_PREFIXE,
                        $this->f->get_submitted_get_value('idxformulaire')
                    );
                    $res = $this->db->getOne($sql);
                    $this->addToLog(__METHOD__."(): db->query(\"".$sql."\");", VERBOSE_MODE);
                    $this->f->isDatabaseError($res);
                    $ordreMax = isset($res) && is_numeric($res) ? $res : 0;
                    $form->setVal('ordre', $ordreMax+1);
                }
            }
            $form->setVal('couleur', '#ff0000');
        }
    }

    /**
     * Crée et initialise les résultats du candidat de l'élection
     * dans la base de données
     *
     * @return void
     */
    public function insert_election_resultat($idElection, $idCandidatElection) {
        $correct = false;
        $message = 'Informations incorrects les résultats des candidats n\'ont pas pu être créés';

        if (! empty($idElection) && ! empty($idCandidatElection)) {
            $unitesElection = $this->f->simple_query(
                'election_unite',
                'election_unite',
                'election',
                $idElection
            );
    
            // Lie chaque candidat à chaque unité de l'élection en ajoutant une nouvelle ligne
            // dans la table election_resultat
            foreach ($unitesElection as $unite) {
                $electionResultat = $this->f->get_element_by_id('election_resultat', ']');
                $data = array(
                    "election_resultat" => null,
                    "election_unite" => $unite,
                    "election_candidat" => $idCandidatElection,
                    "resultat" => null
                );
    
                // Si le traitement ne s'est pas déroulé correctement
                if (! $electionResultat->ajouter($data)) {
                    $correct = false;
                    break;
                }
            }
            $correct = true;
        }

        if ($correct) {
            $this->f->db->commit();
            $message = 'Les résultats du candidat ont été ajoutés';
        } else {
            $this->f->db->rollback();
            $message = 'Erreur lors de l\'ajout des résultats du candidat';
        }

        $this->addToMessage($message);
        return $correct;
    }

    /**
     * Clause select pour la requête de sélection des données de l'enregistrement.
     *
     * @return array liste des champs dans leur ordre d'apparition
     */
    function get_var_sql_forminc__champs() {
        // ré-ordonne les champs pour pouvoir les afficher correctement dans setLayout
        return array(
            "election_candidat",
            "election",
            "candidat",
            "ordre",
            "prefecture",
            "parti_politique",
            "age_moyen",
            "siege",
            "age_moyen_com",
            "siege_com",
            "age_moyen_mep",
            "siege_mep",
            "photo",
            "couleur"
        );
    }

    /**
     * SETTER FORM - setLib
     * 
     * @param formulaire $form Instance formulaire.
     * @param integer $maj Identifant numérique de l'action.
     * 
     * @return void
     */
    function setLib(&$form, $maj) {
        //libelle des champs
        parent::setLib($form, $maj);
        $form->setLib('election_candidat', __('id'));
        $form->setLib('prefecture', __('code candidat prefecture'));
        $form->setLib('age_moyen', __('age moyen de la liste municipale'));
        $form->setLib('siege', __('siege de la liste municipale (calcule)'));
        $form->setLib('age_moyen_com', __('age moyen de la liste communautaire'));
        $form->setLib('siege_com', __('siege de la liste communautaire (calcule)'));
        $form->setLib('age_moyen_mep', __('age moyen de la liste metropolitaine'));
        $form->setLib('siege_mep', __('siege de la liste metropolitaine (calcule)'));
        $form->setLib('parti_politique', __('parti politique'));
    }

    /**
     * SETTER FORM - setLayout
     *
     * @param formulaire $form Instance formulaire.
     * @param integer $maj Identifant numérique de l'action.
     * 
     * @return void
     */
    function setLayout(&$form, $maj) {
        // Fieldset Candidats contiens dans l'ordre : election_candidat, election, candidat,
        // ordre, code candidat prefeture
            $form->setFieldset('election_candidat', 'D', _('Candidats'), "collapsible");
            $form->setFieldset('parti_politique', 'F', '');
        // Fieldset Listes Municipales contiens dans l'ordre : age moyen liste municipale,
        // siege de la liste municipale, age moyen liste communautaire et siège liste communautaire
            $form->setFieldset('age_moyen', 'D', _('Listes Municipales'), "startClosed");
            $form->setFieldset('siege_mep', 'F', '');
        // Fieldset Affichage Animation contiens dans l'ordre : photo et couleur
            $form->setFieldset('photo', 'D', _('Affichage Animation'), "collapsible");
            $form->setBloc('photo', 'D', "", '');
            $form->setBloc('couleur', 'F');
            $form->setFieldset('couleur', 'F', '');
    }

    /**
     * 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();
    }

    /**
     * Indique si l'élection n'est pas archivée
     * @return boolean
     */
    protected function election_non_archivee() {
        $election = $this->f->get_element_by_id('election', $this->getVal('election'));
        return $election->non_archivee();
    }

    /**
     * Supprime tous les résultats du candidat de l'élection
     *
     * @param integer $idElection identifiant de l'élection
     * @return boolean indique si la suppression à réussi
     */
    public function supprimer_resultats_candidat() {
        $succes = true;
        $message = 'Suppression des résultats effectuée';

        // Suppression du lien entre les candidats et les unités
        $resultatsCandidat = $this->f->simple_query(
            'election_resultat',
            'election_resultat',
            'election_candidat',
            $this->getVal('election_candidat')
        );

        foreach ($resultatsCandidat as $resultatId) {
            $resultatCandidat = $this->f->get_element_by_id('election_resultat', $resultatId);

            //Remplissage du tableau de suppression. Le tableau 'val' ne peut pas être
            //utilisé tel quel car il ne contiens pas les noms des différents
            //champs. Pour être utilisable pour la méthode supprimer, on rempli
            //un tableau intermediaire : suppression[champs] = valeur_du_champ
            $suppression = array();
            foreach ($resultatCandidat->champs as $id => $champs) {
                $suppression[$champs] = $resultatCandidat->val[$id];
            }

            if (! $resultatCandidat->supprimer($suppression)) {
                $this->f->db->rollback();
                $message = 'Echec de la suppression des résultats';
                $succes = false;
                break;
            }
            $this->f->db->commit();
        }
        
        $this->addToMessage($message);
        return $succes;
    }

    /**
     * Récupére l'identifiant du lien entre un candidat et l'election à l'aide d'une
     * requête sur l'identifiant du candidat et l'identifiant de l'élection.
     * Renvoie l'instance du candidat.
     *
     * @param integer $idElection identifiant de l'élection
     * @param integer $idCandidat identifiant du candidat
     *
     * @return mixed booleen false en cas d'erreur lors de la requête
     *               election_candidat sinon
     */
    protected function get_election_candidat($idElection, $idCandidat) {
        $sql = sprintf(
            'SELECT
                election_candidat
            FROM
                %selection_candidat
            WHERE
                election = %d AND
                candidat = %d',
            DB_PREFIXE,
            $idElection,
            $idCandidat
        );
        $elecCand = $this->f->db->getOne($sql);
        if ($this->f->is_database_error(
            $sql,
            $elecCand,
            'Erreur lors de la récupération du candidat'
        )) {
            return false;
        }
        $candidat = $this->f->get_element_by_id('election_candidat', $elecCand);
        return $candidat;
    }
}
