<?php
/**
 * Ce script contient la définition de la classe *om_widget*.
 *
 * @package openresultat
 * @version SVN : $Id$
 */

require_once PATH_OPENMAIRIE."obj/om_widget.class.php";

/**
 * Définition de la classe *om_widget*.
 */
class om_widget extends om_widget_core {
    public function view_widget__election($content = null) {
        $elections = array();
        $query = sprintf(
            'SELECT to_char(election.date ,\'DD/MM/YYYY\') as election_date, * FROM %1$selection WHERE is_centaine IS NOT TRUE AND workflow NOT LIKE \'Archivage\'',
            DB_PREFIXE
        );
        $res = $this->f->db->query($query);
        $this->f->isDatabaseError($res);
        while ($row = $res->fetchrow(DB_FETCHMODE_ASSOC)) {
            $elections[] = $row;
        }
        if (count($elections) == 0) {
            echo __("Aucune élection en cours.");
            return false;
        }
        $content = "";
        $workflow_icon = array(
            'Paramétrage'=> 'settings-3-line',  
            'Simulation'=> 'compasses-2-line',  
            'Saisie'=> 'edit-line',  
            'Finalisation'=> 'file-check-line',
        );
        $line_template = '
        <a href="%1$s" class="list-group-item list-group-item-action">
            <h4>%2$s
                <small style="display:block">%3$s</small>
            </h4>
            <span class="badge election-step %4$s"><i class="ri-%5$s"></i>%4$s</span>
        </a>
        ';
        $out = '<div class="list-group">';
        foreach ($elections as $key => $value) {
            $out .= sprintf(
                $line_template,
                OM_ROUTE_FORM."&obj=election&action=3&idx=".$value["election"],
                $value["libelle"],
                $value["election_date"],
                $value["workflow"],
                $workflow_icon[$value["workflow"]],

            );
        }
        $out .= '</div>';
        echo $out;
        return false;

    }

    public function view_widget__web($content = null) {
        $contenuWidget = 'Le portail web n\'est pas actif.';
        if ($this->portail_actif()) {
            $contenuWidget = sprintf(
                '<div class="link-web"><a href="%1$s" target="blank" title="Lien externe"><i class="ri-door-open-line"></i><h4>%2$s <i class="ri-external-link-line"></i></h4></a></div>',
                "../web/",
                __("Accéder au portail web de publication des résultats électoraux")
            );
        }
        echo $contenuWidget;
        return false;
    }

    /**
     * Parse une chaîne brute de paramètres en tableau clé=>valeur filtré.
     *
     * @param string|null $content Contenu brut à parser (chaque ligne au format "clé=valeur")
     * @param array $params Liste des clés autorisées à extraire
     * 
     * @return array Tableau associatif ['clé' => 'valeur', ...] avec clés autorisées uniquement
     */
    function get_arguments(?string $content = null, array $params = []): array {
        $arguments = [];

        // On divise le contenu en lignes, même si $content est null => explode retourne ['']
        $lines = explode("\n", (string)$content);

        foreach ($lines as $line) {
            // Chaque ligne doit être de la forme "clé=valeur"
            $parts = explode("=", $line, 2);

            // Condition : on a bien 2 parties et la clé est dans la liste autorisée
            if (count($parts) === 2) {
                $key = trim($parts[0]);
                $value = trim($parts[1]);
                if (in_array($key, $params, true)) {
                    $arguments[$key] = $value;
                }
            }
        }

        return $arguments;
    }

    /**
     * Widget de saisie des résultats électoraux.
     *
     * Ce widget gère les requêtes AJAX en mode "résultat" et affiche
     * soit uniquement un sélecteur d’élection sous forme de tableau,
     * soit le formulaire complet de saisie des résultats, selon le contexte.
     *
     * @param string|null $content Contenu optionnel contenant des paramètres d’affichage (ex : listebureau=false).
     * @return bool|string Retourne false si aucun widget à afficher,
     *                     ou le rendu HTML du sélecteur d’élection.
     */
    public function view_widget__saisie_resultat($content = null)
{
    // Instanciation du formulaire lié aux élections
    $Election = $this->f->get_inst__om_dbform([
        'obj' => 'election',
        'idx' => ''
    ]);

    // Récupération de l’ID de l’acteur connecté en session
    $sessionActeurId = $Election->fetchActeurId();

    // --- 1) Mode tableau (listebureau=false) -> on affiche UNIQUEMENT le sélecteur + tableaux côté PHP
    if (!$this->shouldShowWidget($content)) {
        $elections = $Election->fetchElectionsFiltered($sessionActeurId);
        if (empty($elections)) {
            echo '<div class="msg-erreur">' . __('Aucune élection en cours.') . '</div>';
            return false;
        }
        // Rendu 100% PHP (pas de JS/API)
        $this->renderTableWidget($elections);
        return false;
    }

    // --- 2) Sinon : affichage classique du formulaire de saisie
    $resolvedActeurId = (is_numeric($sessionActeurId) && (int)$sessionActeurId > 0)
        ? (int)$sessionActeurId
        : $Election->fetchActeurId();

    $elections = $Election->fetchElectionsFiltered($resolvedActeurId);
    if (empty($elections)) {
        echo '<div class="msg-erreur">' . __('Aucune élection en cours.') . '</div>';
        return false;
    }

    // Sécurité : si après résolution on reste en mode tableau, renvoyer le tableau
    if (!$this->shouldShowWidget($content)) {
        $this->renderTableWidget($elections);
        return false;
    }

    // Formulaire classique
    $this->renderResultatWidget($elections, [], 0);
    return false;
}

    /**
     * Widget de saisie de participation électorale.
     *
     * Ce widget traite les requêtes AJAX en mode "participation".
     * Il affiche le formulaire complet de participation avec les élections,
     * tranches et unités associées. Si aucune élection n’est disponible,
     * un message d’erreur est affiché.
     *
     * @param string|null $content Contenu optionnel, non utilisé ici.
     * @return bool Toujours false pour indiquer la fin du traitement sans renvoyer de contenu.
     */
    public function view_widget__saisie_participation($content = null)
    {
        // Instanciation du formulaire liée aux élections
        $Election = $this->f->get_inst__om_dbform([
            'obj' => 'election',
            'idx' => ''
        ]);

        // Récupération de l’ID de l’acteur courant connecté en session
        $acteurId = $Election->fetchActeurId();

        // Récupération des élections filtrées selon le mode 'participation' et l’acteur
        $elections = $Election->fetchElectionsFiltered($acteurId);

        // Si aucune élection disponible, afficher un message d’erreur
        if (empty($elections)) {
            echo '<div class="msg-erreur">' . __('Aucune élection en cours.') . '</div>';
            return false;
        }

        // Rendu du formulaire complet de saisie de participation
        $this->renderParticipationWidget($elections, [], [], 0);

        // Fin du rendu, retourne toujours false
        return false;
    }

    /**
     * Détermine si le widget complet doit s’afficher ou si seul le sélecteur de table doit être rendu.
     *
     * Cette méthode analyse le contenu fourni afin d’en extraire des arguments,
     * notamment la présence et la valeur de l’argument 'listebureau'.
     * Si 'listebureau' est défini à 'false', le widget complet ne doit pas s’afficher.
     *
     * @param string $content Contenu textuel pouvant contenir des arguments (ex: listebureau=false).
     * @return bool Renvoie true si le widget complet doit être affiché,
     *              false si seul le sélecteur doit être montré.
     */
    private function shouldShowWidget($content): bool
    {
        // Extraction des arguments du contenu (cherche spécifiquement 'listebureau')
        $args = $this->get_arguments($content, ['listebureau']);

        // Si 'listebureau' est défini et égal à 'false' après nettoyage, alors ne pas montrer le widget complet
        if (isset($args['listebureau']) && trim($args['listebureau']) === 'false') {
            return false;
        }

        // Sinon, afficher le widget complet
        return true;
    }

    private function renderTableWidget(array $elections): void
    {
        // Instance
        $Election   = $this->f->get_inst__om_dbform(['obj' => 'election','idx' => '']);
        $acteurId   = $Election->fetchActeurId();

        // Élection sélectionnée (soumise par POST), sinon 1ère clé
        $posted     = (isset($_POST['__form']) && $_POST['__form'] === 'table');
        $selElection= $posted && isset($_POST['tbl_election']) ? (int)$_POST['tbl_election'] : (int)array_key_first($elections);
        if (!isset($elections[$selElection])) {
            $selElection = (int)array_key_first($elections);
        }

        // Options du select
        $opts = '';
        foreach ($elections as $eid => $lib) {
            $sel  = ((int)$eid === (int)$selElection) ? ' selected' : '';
            $opts .= '<option value="'.(int)$eid.'"'.$sel.'>'.htmlspecialchars($lib).'</option>';
        }

        // Récupération des centaines de l’élection de base
        $centaines = $Election->fetchCentaines($selElection); // ex: [['id'=>'123','label'=>'Centaine X'], ...]
        // Rendu
        echo '<div class="widget-saisie-table" style="padding:1em;">';

        // Sélecteur d’élection qui soumet en POST pour recharger les tableaux
        echo '<form method="post" action="" style="margin-bottom:1.5em;">'
            . '<input type="hidden" name="__form" value="table">'
            . '<label for="tbl-election" style="font-weight:bold;">' . __('Élection') . '</label><br>'
            . '<select id="tbl-election" name="tbl_election" '
            . 'style="width:100%; max-width:320px; padding:0.4em; margin-top:0.5em;" '
            . 'onchange="this.form.submit()">'
            . $opts
            . '</select>'
            . '</form>';

        // SECTION 1 : Résultat (élection “de base”)
        echo $this->buildUnitsSectionHtml(
            $Election,
            $selElection,
            $selElection,
            $acteurId,
            __('Saisie des résultats')
        );

        // SECTION 2..N : Chaque centaine (mêmes unités affichées, mais idx issus de la centaine)
        if (!empty($centaines)) {
            foreach ($centaines as $c) {
                $centaineId    = isset($c['id']) ? (int)$c['id'] : null;
                $centaineLabel = isset($c['label']) ? (string)$c['label'] : ('Centaine #'.$centaineId);
                if ($centaineId === null) {
                    continue;
                }

                echo $this->buildUnitsSectionHtml(
                    $Election,
                    $selElection,
                    $centaineId,
                    $acteurId,
                    htmlspecialchars($centaineLabel)
                );
            }
        }

        echo '</div>'; // .widget-saisie-table
    }

    /**
     * Construit le HTML d’une section (titre + tableau) pour une élection “d’affichage”
     * et une élection “d’action” (utilisée pour calculer les idx des boutons).
     *
     * - displayElectionId : d’où l’on tire la liste des unités/bureaux à afficher.
     * - actionElectionId  : avec quoi on calcule l’idx pour “Voir/Saisir”.
     */
    private function buildUnitsSectionHtml($Election, int $displayElectionId, int $actionElectionId, $acteurId, string $titre): string
    {
        $bureaux = $Election->fetchAllBureauxForElection($displayElectionId, $acteurId);
        
        $html  = '<div style="margin-bottom: 2em;">'
            .   '<h3 style="margin: 0 0 0.5em; font-size: 1.1em;">' . htmlspecialchars($titre) . '</h3>';

        if (empty($bureaux)) {
            $html .= '<div class="msg-info">' . __('Aucune unité disponible pour cette election.') . '</div></div>';
            return $html;
        }

        $html .= '<table style="width:100%; margin-bottom:1em; border-collapse:collapse;">'
            .   '<thead>'
            .     '<tr>'
            .       '<th style="text-align:left; padding:0.5em; border-bottom:1px solid #ddd;">' . __('Unité') . '</th>'
            .       '<th style="text-align:left; padding:0.5em; border-bottom:1px solid #ddd;">' . __('Saisie') . '</th>'
            .       '<th style="text-align:left; padding:0.5em; border-bottom:1px solid #ddd;">' . __('Action') . '</th>'
            .     '</tr>'
            .   '</thead>'
            .   '<tbody>';

        foreach ($bureaux as $b) {
            $bid  = (int)$b['id'];
            $blbl = htmlspecialchars($b['label']);

            // Status = appel direct avec l’élection d’action + l’unité
            $statusHtml = '';
            try {
                $statusHtml = (string)$Election->get_status_election($actionElectionId, $bid);
            } catch (\Throwable $e) {
                $statusHtml = '';
            }

            // Idx pour la popup (calculé à partir de l’élection d’action + unité)
            $idx = (int)$Election->fetchDefaultIdx($actionElectionId, $bid);

            // URL pour la popup
            $url  = 'index.php?module=sousform'
                . '&obj=election_unite'
                . '&idx=' . $idx
                . '&action=1'
                . '&retour=form';

            $html .= '<tr>'
                .    '<td style="padding:0.75em 0.5em; border-bottom:1px solid #f0f0f0;">' . $blbl . '</td>'
                .    '<td style="padding:0.75em 0.5em; border-bottom:1px solid #f0f0f0; color:#333;">' . $statusHtml . '</td>'
                .    '<td style="padding:0.75em 0.5em; border-bottom:1px solid #f0f0f0;">'
                .      '<button type="button" '
                .         'onclick="popupIt(\'election_unite\', \'' . htmlspecialchars($url) . '\', \'70%\', \'auto\', null, null, null)" '
                .         'style="padding:0.45em 0.9em; background:#0d6efd; color:#fff; border:none; border-radius:0.4em; font-weight:600; cursor:pointer;">'
                .        __('VOIR')
                .      '</button>'
                .    '</td>'
                .  '</tr>';
        }

        $html .=   '</tbody>'
            . '</table>'
            . '</div>';

        return $html;
    }

    /**
     * Affiche le formulaire complet de saisie des résultats électoraux.
     *
     * Le formulaire est dynamique, s'adaptant aux données POST reçues et au contexte
     * de session pour gérer les élections, les types de saisie (résultat ou centaines),
     * et les bureaux disponibles. Le rendu inclut des sélecteurs et un bouton de validation.
     *
     * @param array $elections       Tableau associatif des élections [id => libellé].
     * @param array $ignoredBureaux  Tableau d’IDs de bureaux à ignorer (non utilisé dans cette fonction).
     * @param int   $ignoredIdx      Index ignoré (non utilisé dans cette fonction).
     */
    public function renderResultatWidget(array $elections, array $ignoredBureaux = [], int $ignoredIdx = 0): void
    {
        // Instance
        $Election = $this->f->get_inst__om_dbform(['obj' => 'election','idx' => '']);

        // POST
        $isResSubmit    = isset($_POST['__form']) && $_POST['__form'] === 'res';
        $postedElection = ($isResSubmit && isset($_POST['res_election'])) ? (int)$_POST['res_election'] : null;
        $postedBureau   = ($isResSubmit && isset($_POST['res_bureau']))   ? (int)$_POST['res_bureau']   : null;
        $postedType     = ($isResSubmit && array_key_exists('res_type', $_POST)) ? $_POST['res_type'] : null;

        // Base election
        $baseElection = $postedElection ?? (int)array_key_first($elections);
        if (!isset($elections[$baseElection])) {
            $baseElection = (int)array_key_first($elections);
        }

        // Sessions: base election change
        $lastBaseElection     = $_SESSION['__widget_res_last_base_election'] ?? null;
        $baseElectionChanged  = ($lastBaseElection !== null && (int)$lastBaseElection !== (int)$baseElection);
        $_SESSION['__widget_res_last_base_election'] = (int)$baseElection;

        // Types/centaines
        $typesOptionsArray = [['id' => 'resultat', 'label' => __('Résultat')]];
        $centaines = $Election->fetchCentaines($baseElection);
        $centaineIds = [];
        foreach ($centaines as $c) {
            $cid = (string)$c['id'];
            $centaineIds[] = $cid;
            $typesOptionsArray[] = ['id' => $cid, 'label' => $c['label']];
        }

        // Type sélectionné
        $postedTypeStr = $postedType === null ? null : (string)$postedType;
        if ($baseElectionChanged && $postedTypeStr !== null && $postedTypeStr !== 'resultat' && !in_array($postedTypeStr, $centaineIds, true)) {
            $selectedT = 'resultat';
            $postedBureau = null;
        } else {
            $selectedT = ($postedTypeStr !== null && ($postedTypeStr === 'resultat' || in_array($postedTypeStr, $centaineIds, true)))
                ? $postedTypeStr
                : 'resultat';
        }

        // Élection effective
        $effectiveElection = ($selectedT !== 'resultat') ? (int)$selectedT : (int)$baseElection;

        // Sessions: effective election change
        $lastEffectiveElection     = $_SESSION['__widget_res_last_effective_election'] ?? null;
        $effectiveElectionChanged  = ($lastEffectiveElection !== null && (int)$lastEffectiveElection !== (int)$effectiveElection);
        $_SESSION['__widget_res_last_effective_election'] = (int)$effectiveElection;

        // Reset bureau si changement
        $mustResetBureau = $baseElectionChanged || $effectiveElectionChanged;

        // Bureaux
        $resolvedActeurId = $Election->fetchActeurId();
        $bureaux = $Election->fetchAllBureauxForElection($effectiveElection, $resolvedActeurId);
        if (empty($bureaux)) {
            echo '<div class="msg-info">' . __('Aucune election pour cette election.') . '</div>';
            return;
        }
        $bureauIds = array_map(static fn($b) => (int)$b['id'], $bureaux);
        $firstBureauId = (int)$bureaux[0]['id'];

        // Bureau sélectionné
        if ($mustResetBureau) {
            $selectedB = $firstBureauId;
        } else {
            $selectedB = ($postedBureau !== null && in_array((int)$postedBureau, $bureauIds, true)) ? (int)$postedBureau : $firstBureauId;
        }

        // Idx
        $idx = $Election->fetchDefaultIdx($effectiveElection, $selectedB);

        // Options type
        $optsType = '';
        foreach ($typesOptionsArray as $t) {
            $sel = ((string)$t['id'] === (string)$selectedT) ? ' selected' : '';
            $optsType .= '<option value="' . htmlspecialchars((string)$t['id']) . '"' . $sel . '>' . htmlspecialchars($t['label']) . '</option>';
        }

        // Options bureau
        $optsBureau = '';
        foreach ($bureaux as $b) {
            $sel = ((int)$b['id'] === (int)$selectedB) ? ' selected' : '';
            $optsBureau .= '<option value="' . (int)$b['id'] . '"' . $sel . '>' . htmlspecialchars($b['label']) . '</option>';
        }

        // Formulaire uniquement
        echo '<form id="widget-saisie-form-res" method="post" action="">'
            . '<input type="hidden" name="__form" value="res">'
            . '<label for="res-election">' . __('Élection') . '</label><br>'
            . '<select id="res-election" name="res_election" onchange="this.form.submit()">';
        foreach ($elections as $eid => $lib) {
            $sel = ((int)$eid === (int)$baseElection) ? ' selected' : '';
            echo '<option value="' . (int)$eid . '"' . $sel . '>' . htmlspecialchars($lib) . '</option>';
        }
        echo '</select><br><br>'
            . '<label for="res-type">' . __('Type de saisie') . '</label><br>'
            . '<select id="res-type" name="res_type" onchange="this.form.submit()">' . $optsType . '</select><br><br>'
            . '<label for="res-bureau">' . __('Bureau') . '</label><br>'
            . '<select id="res-bureau" name="res_bureau" onchange="this.form.submit()">' . $optsBureau . '</select><br><br>'
            . '<input type="hidden" id="res-idx" name="idx" value="' . (int)$idx . '">'
            . '<button type="button" id="lancer-resultat-btn">' . __('SAISIR LES RÉSULTATS') . '</button>'
            . '</form>'
            . '<script>initResultatWidget();</script>';
    }


    /**
     * Affiche le formulaire dynamique de saisie de participation électorale.
     *
     * Le formulaire s’adapte aux données POST reçues et au contexte (acteurs, délégations),
     * en affichant les sélecteurs d’élections, tranches horaires, bureaux selon les droits.
     * Le rendu est intégralement géré en PHP avec soumission via formulaire.
     *
     * @param array $elections      Tableau des élections sous la forme [id => libellé].
     * @param array $ignoredTranches Tableau des tranches ignorées (non utilisées).
     * @param array $ignoredUnites  Tableau des unités ignorées (non utilisées).
     * @param int   $ignoredIdx     Index ignoré (non utilisé).
     */
    private function renderParticipationWidget(array $elections, array $ignoredTranches, array $ignoredUnites, int $ignoredIdx): void
    {
        // Instanciation des formulaires 'election' et 'unite'
        $Election = $this->f->get_inst__om_dbform(['obj' => 'election', 'idx' => '']);
        $Unite    = $this->f->get_inst__om_dbform(['obj' => 'unite', 'idx' => '']);

        // --- 1) Sélection de l’élection active (POST ou première élection disponible)
        $selectedE = isset($_POST['election']) ? (int) $_POST['election'] : (int) array_key_first($elections);

        // --- 2) Récupération des tranches horaires associées à l’élection sélectionnée
        $tranches = $Election->fetchTranches($selectedE);

        // Affiche un message et arrête si aucune tranche disponible
        if (empty($tranches)) {
            echo '<div class="msg-info">' . __('Aucune tranche pour cette élection.') . '</div>';
            return;
        }

        // --- 3) Sélection de la tranche active (POST ou première)
        $selectedT = isset($_POST['tranche']) ? (int) $_POST['tranche'] : (int) array_key_first($tranches);

        // --- 4) Récupération des bureaux pour l’élection et acteur courant
        $resolvedActeurId = $Election->fetchActeurId();
        $bureaux          = $Election->fetchAllBureauxForElection($selectedE, $resolvedActeurId);

        // --- 5) Vérifie si une délégation est active pour cette élection
        $isDelegation = false;
        if (method_exists($Election, 'is_election_delegation_participation')) {
            $isDelegation = (bool) $Election->is_election_delegation_participation($selectedE);
        } elseif (method_exists($Election, 'is_election_delegation_saisie')) {
            $isDelegation = (bool) $Election->is_election_delegation_saisie($selectedE);
        }

        // --- 6) Construction des options HTML pour le select bureau si délégation active
        $selectedB  = null;
        $optsBureau = '';
        if ($isDelegation) {
            if (empty($bureaux)) {
                $optsBureau = '';
            } else {
                $bureauIds     = array_map(fn($b) => (int) $b['id'], $bureaux);
                $firstBureauId = (int) $bureaux[0]['id'];

                $postedBureau = isset($_POST['bureau']) ? (int) $_POST['bureau'] : null;
                $selectedB    = ($postedBureau !== null && in_array($postedBureau, $bureauIds, true))
                    ? $postedBureau
                    : $firstBureauId;

                foreach ($bureaux as $b) {
                    $sel         = ((int) $b['id'] === $selectedB) ? ' selected' : '';
                    $optsBureau .= '<option value="' . (int) $b['id'] . '"' . $sel . '>' . htmlspecialchars($b['label']) . '</option>';
                }
            }
        }

        // --- 7) Calcul du paramètre d’index selon délégation (idx de l’unité) ou participation
        if ($isDelegation) {
            $idx = $Election->fetchElectionUnite($selectedE, $selectedB);
        } else {
            $idxRow = $Election->fetchParticipationElectionRow($selectedE, $selectedT);
            $idx    = isset($idxRow['participation_election']) ? (int) $idxRow['participation_election'] : 0;
        }

        // --- 8) Construction des options HTML des sélecteurs élections et tranches
        $optsElection = '';
        foreach ($elections as $eid => $libelle) {
            $sel          = ((int) $eid === $selectedE) ? ' selected' : '';
            $optsElection .= '<option value="' . htmlspecialchars((string) $eid) . '"' . $sel . '>' . htmlspecialchars($libelle) . '</option>';
        }
        $optsTranche = '';
        foreach ($tranches as $tid => $libelle) {
            $sel         = ((int) $tid === $selectedT) ? ' selected' : '';
            $optsTranche .= '<option value="' . htmlspecialchars((string) $tid) . '"' . $sel . '>' . htmlspecialchars($libelle) . '</option>';
        }

        // --- 9) Rendu complet du formulaire HTML dynamique
        echo '<form id="widget-participation-form" method="post" action="">'
            . '<label for="widget-election">' . __('Élection') . '</label><br>'
            . '<select id="widget-election" name="election" onchange="this.form.submit()">' . $optsElection . '</select><br><br>';

        // Affichage conditionnel du select bureau si délégation active
        if ($isDelegation) {
            echo '<label for="widget-bureau">' . __('Bureau') . '</label><br>';
            if ($optsBureau !== '') {
                echo '<select id="widget-bureau" name="bureau" onchange="this.form.submit()">' . $optsBureau . '</select><br><br>';
            } else {
                echo '<div class="msg-info">' . __('Aucune election pour ce widget.') . '</div><br>';
            }

            // Ici on cache l'HORAIRE car le bureau est affiché
            echo '<div id="horaire-field" style="display:none;">'
                . '<label for="widget-tranche">' . __('Horaire') . '</label><br>'
                . '<select id="widget-tranche" name="tranche" onchange="this.form.submit()">' . $optsTranche . '</select><br><br>'
                . '</div>';
        } else {
            // Sinon on montre l'HORAIRE normalement
            echo '<div id="horaire-field">'
                . '<label for="widget-tranche">' . __('Horaire') . '</label><br>'
                . '<select id="widget-tranche" name="tranche" onchange="this.form.submit()">' . $optsTranche . '</select><br><br>'
                . '</div>';
        }

        echo '<input type="hidden" id="part-idx" name="idx" value="' . (int) $idx . '">'
            . '<button type="button" id="lancer-participation-btn">' . __('Saisir la participation') . '</button>'
            . '</form>'
            . '<script>initParticipationWidget();</script>';
    }

public function view_widget__animation($content = null) {
    $animations = array();

    $query = sprintf(
        'SELECT e1.election as election_id, e1.libelle as election_libelle, animation.libelle as animation_libelle, * 
         FROM %1$sanimation 
         INNER JOIN %1$selection as e1 on animation.election = e1.election 
         LEFT JOIN %1$selection as e2 on e1.election_reference = e2.election 
         WHERE ((e2.workflow IS NULL OR e2.workflow NOT LIKE \'Archivage\') AND e1.workflow NOT LIKE \'Archivage\') 
         ORDER BY e1.date DESC, e1.election, animation.libelle',
        DB_PREFIXE
    );

    $res = $this->f->db->query($query);
    $this->f->isDatabaseError($res);

    while ($row = $res->fetchrow(DB_FETCHMODE_ASSOC)) {
        $animations[] = $row;
    }

    if (count($animations) == 0) {
        echo __("Aucune animation en cours.");
        return false;
    }

    $out = "<ul>";
    foreach ($animations as $value) {
        $out .= sprintf(
            '<li><a target="_blank" href="../aff/animation.php?idx=%1$d&identifier=%2$s">%3$s - %4$s</a></li>',
            (int)$value["election_id"],
            htmlspecialchars($value["animation"]),
            htmlspecialchars($value["election_libelle"]),
            htmlspecialchars($value["animation_libelle"])
        );
    }
    $out .= "</ul>";

    echo $out;
    return false;
}




    /**
     * Vérifie si le portail web est actif.
     * La vérification se fait via une requête sql qui récupère le
     * modèle web actif. Si aucun modèle web n'est récupéré c'est que
     * le portail web n'est pas actif.
     *
     * /!\ cette méthode renvoie false en cas d'erreur de base de données
     *
     * @return boolean
     */
    protected function portail_actif() {
        $sql = sprintf(
            'SELECT
                web
            FROM
                %1$sweb
            WHERE
                actif IS TRUE',
            DB_PREFIXE
        );
        $result = $this->f->get_one_result_from_db_query($sql);
        if ($result['code'] == 'KO') {
            return false;
        }
        // Si le portail web est actif on a un résultat si ce n'est pas le cas
        // la requête ne renverra rien
        return ! empty($result['result']);
    }
}
