<?php
/**
 * Basisklasse für Livewire-Form-Components
 *
 * @todo        - Es könnte darüber nachgedacht werden ob diese Klasse eine eigene Locale-Datei
 *                erhalten soll, in der zum Beispiel die Standardüberschrift für die Notification
 *                definiert wird. Wenn die Standardüberschrift implementiert wird, dann sollte es in
 *                jedem Fall eine eigene Locale-Datei geben, da die Überschrift nichts in der Locale
 *                global.php verloren hat.
 *
 *              - Template-Variablen in einen Array ("modal") verpacken.
 *
 * @version     1.0.$Revision:$
 * @version     SVN: $Id:$
 * @package     bplan-base/globals
 * @subpackage  LivewireComponents
 * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
 * @copyright   Copyright (C) 2025, 2026 Wassilios Meletiadis <https://www.bplan-solutions.de/>
 * /Δ\
 */

namespace BplanBase\Globals\Livewire\Core\Global;


use BplanBase\Globals\Traits\Core\NotificationTrait;
use BplanBase\Globals\Traits\Core\ValidationTrait;
use BplanBase\Globals\Livewire\Core\Global\Notification;
use Livewire\Component;


/**
 * Basisklasse für Livewire-Formularkomponenten
 *
 * Die Klasse erweitert eine abgeleitete Livewire-Component um die folgenden Funktionalitäten:
 * - Modale Dialogfenster
 * - Notifications
 * - Optimierte Fehlermeldungen für Formulare
 *
 * Um die erweiterte Funktionalität zu nutzen muss die eigene Component von dieser Klasse abgeleitet
 * werden:
 *
 *  <pre>
 *    <code>
 *      use BplanBase\Globals\Livewire\FormComponentBase;
 *&nbsp;
 *      class MyForm extends FormComponentBase
 *      {
 *          ...
 *      }
 *    </code>
 *  </pre>
 *  <strong>Modale Dialogfenster</strong>
 *
 * Für die Verwendung der Dialogfenster muss das zugehörige Template mit einer herkömmlichen
 * Blade include-Anweisung eingebunden werden:
 *
 *  <pre>
 *    <code>
 *      &#64;include('livewire/bplan/modal-dialog')
 *    </code>
 *  </pre>
 * Zum Ein- oder Ausblenden eines Dialogs stehen die Methoden showModal() (@see FormComponentBase::showModal())
 * und hideModal() (@see FormComponentBase::hideModal()) zur Verfügung.
 * Die Parameter für showModal() sind der Typ des Modal-Fensters, ein Methodennamen, die anzuzeigende
 * Meldung und eine (optionale) Überschrift.
 *
 * Beispiel:
 *  <pre>
 *    <code>
 *      $this->showModal(self::MODAL_TYPE__CONFIRM, 'delete', 'Wirklich löschen?', 'Bitte bestätigen')
 *    </code>
 *  </pre>
 * Als Typ muss eine der MODAL_TYPE__*-Konstanten angegeben werden. Die folgenden Typen stehen zur
 * Verfügung:
 * - ALERT
 * - CONFIRM
 * - PROMPT
 *
 * Der Methodenname muss dem Namen einer Methode der Component entsprechen, die beim Betätigen des
 * OK-Buttons des Modal-Fensters aufgerufen werden soll.
 *
 *
 *  <strong>Notifications</strong>
 *
 * Zur Verwendung der Notifications muss das Notification-Template im Livewire-Stil eingebunden
 * werden. Die Einbindung kann, im Layout- oder im Formular-Template, mit folgender Codezeile
 * erfolgen:
 *
 *  <pre>
 *    <code>
 *      &lt;livewire:bplan.notification /&gt;
 *    </code>
 *  </pre>
 * Anschließend können die Methoden _hideNotification() und _showNotification(), die im Trait
 * "NotificationTrait" (@see App\bplan\Livewire\NotificationTrait) definiert sind, in der
 * abgeleiteten Component-Klasse verwendet werden.
 *
 * Der Trait mit dieser Funktionalität kann auch einzeln verwendet werden (@see App\bplan\Livewire\NotificationTrait).
 *
 *
 *   <strong>Optimierte Fehlermeldungen für Formulare</strong>
 *
 * Mit der Installation von Livewire wird auch die Locale-Datei "validation.php" installiert. Darin
 * sind Fehlermeldungen, passend zu den Validation Rules von Laravel, definiert. Allerdings wird in
 * diesen Fehlermeldungen immer der interne Feldname (Variablenname) verwendet, um das Feld zu
 * benennen. Für den Endanwender ist das unter Umständen nichtssagend oder sogar verwirrend.
 *
 * Diese Erweiterung schafft Möglichkeit eigene Standardfehlermeldungen (passend zu einer Rule) oder
 * auch vollständig individuelle Fehlermeldungen zu definieren, in denen das Label des jeweiligen
 * Eingabefeldes (also das was der User auch im Formular sieht) verwendet wird.
 *
 * Eigene Standardfehlermeldungen werden in der Locale-Datei "global.php" (lang/#/global.php)
 * definiert. Der Schlüssel der Fehlermeldungen muss dabei immer aus dem Präfix "form-error" und der
 * Laravel Validation-Rule (@see https://laravel.com/docs/9.x/validation#available-validation-rules),
 * getrennt durch einen Punkt (.), gebildet werden.
 *
 * Beispiele:
 *
 *  <pre>
 *    <code>
 *      'form-error.integer'  => 'Im Feld ":attribute" wird eine Ganzzahl erwartet.',
 *      'form-error.required' => 'Das Feld ":attribute" ist ein Pflichtfeld.',
 *    </code>
 *  </pre>
 * Um den Platzhalter ":attribute" zur Laufzeit durch das im Formular verwendete Label ersetzen zu
 * können, müssen auch die Schlüssel der Label in einem speziellen Format angelegt werdn.
 * Jeder Schlüssel muss aus dem Präfix "label", einem Punkt (.) und dem Variablennamen zusammengesetzt
 * werden.
 *
 * Beispiele:
 *
 *  <pre>
 *    <code>
 *      'label.email'                 => 'E-Mail Adresse',
 *      'label.organizationalunit_id' => 'Organisationseinheit',
 *    </code>
 *  </pre>
 * Damit die Locale-Datei zur Component gefunden werden kann, ist es erforderlich den Dateinamen
 * (ohne Dateiendung) in der Component-Klasse, in der Objekt-Variablen "$_localeFile", anzugeben.
 *
 * Beispiel:
 *
 *  <pre>
 *    <code>
 *       protected $_localeFile = 'user-form';
 *    </code>
 *  </pre>
 * In der gleichen Datei können auch die individuellen Fehlermeldungen definiert werden.
 *
 * Beim Aufbau der Schlüssel der individuellen Fehlermeldungen muss wieder das Präfix "form-error"
 * verwendet werden. Diesmal gefolgt vom internen Feldnamen und der Laravel Validation-Rule, jeweils
 * getrennt durch einen Punkt.
 *
 * Beispiele:
 *
 *  <pre>
 *    <code>
 *      'form-error.email.required'                 => 'Der Wert des Feldes ":attribute" ist eine Pflichtangabe.',
 *      'form-error.email.email'                    => 'Die angegebene E-Mail-Adresse hat ein ungültiges Format.',
 *      'form-error.organizationalunit_id.required' => 'Es wurde keine :attribute ausgewählt.',
 *    </code>
 *  </pre>
 * Der Trait mit dieser Funktionalität kann auch einzeln verwendet werden (@see use BplanBase\Globals\Livewire\ValidationTrait).
 *
 * @version     1.0.0 / 2025-05-25
 * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
 *
 */
class FormComponentBase extends Component
{

/* +++ TRAITS +++ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */


    use NotificationTrait;
    use ValidationTrait;


/* +++ CLASS CONSTANTS +++ ++++++++++++++++++++++++++++++++++++++++++++++++++ */


    /**
     * Konstante für die Steuerung des Typs eines modalen Dialogfensters
     */
    const MODAL_TYPE__ALERT   = 'ALERT';


    /**
     * Konstante für die Steuerung des Typs eines modalen Dialogfensters
     */
    const MODAL_TYPE__CONFIRM = 'CONFIRM';


    /**
     * Konstante für die Steuerung des Typs eines modalen Dialogfensters
     *
     * @todo    Noch nicht implementiert
     */
    const MODAL_TYPE__PROMPT  = 'PROMPT';


    /**
     * Konstante zur Verwendung in der Component-Klasse
     *
     * Diese Konstante kann in der Komponentenklasse direkt verwendet werden und erspart es so,
     * dass die Component selbst nochmal die Notification-Klasse per "use" einbinden muss.
     *
     * @var    string NOTIFICATION_TYPE__ERROR
     */
    const NOTIFICATION_TYPE__ERROR = Notification::TYPE__ERROR;


    /**
     * Konstante zur Verwendung in der Component-Klasse
     *
     * Diese Konstante kann in der Komponentenklasse direkt verwendet werden und erspart es so,
     * dass die Component selbst nochmal die Notification-Klasse per "use" einbinden muss.
     *
     * @var    string NOTIFICATION_TYPE__NOTICE
     */
    const NOTIFICATION_TYPE__NOTICE = Notification::TYPE__NOTICE;


    /**
     * Konstante zur Verwendung in der Component-Klasse
     *
     * Diese Konstante kann in der Komponentenklasse direkt verwendet werden und erspart es so,
     * dass die Component selbst nochmal die Notification-Klasse per "use" einbinden muss.
     *
     * @var    string NOTIFICATION_TYPE__SUCCESS
     */
    const NOTIFICATION_TYPE__SUCCESS = Notification::TYPE__SUCCESS;


    /**
     * Konstante zur Verwendung in der Component-Klasse
     *
     * Diese Konstante kann in der Komponentenklasse direkt verwendet werden und erspart es so,
     * dass die Component selbst nochmal die Notification-Klasse per "use" einbinden muss.
     *
     * @var    string TYPE__WARNING
     */
    const NOTIFICATION_TYPE__WARNING = Notification::TYPE__WARNING;


/* +++ OBJECT MEMBERS +++ +++++++++++++++++++++++++++++++++++++++++++++++++++ */


    /**
     * Nimmt die Überschrift für den Modal-Dialog auf
     *
     * @var        string $modalCaption
     */
    public $modalCaption;


    /**
     * Nimmt die Nachricht für den Modal-Dialog auf
     *
     * @var         string $modalMessage
     */
    public $modalMessage;


    /**
     * Nimmt den Namen der Methode, die vom Modal-Dialog aufgerufen werden kann, auf
     *
     * @var         string $modalMethod
     */
    public $modalMethod;


    /**
     * Definiert den Typ des Modal-Dialogs
     *
     * @var         string $modalType
     */
    public $modalType = self::MODAL_TYPE__ALERT;


    /**
     * Steuert die Sichtbarkeit des Modal-Dialogs
     *
     * @var         boolean $modalVisibility
     */
    public $modalVisibility = false;


/* +++ CLASS MEMBERS +++ ++++++++++++++++++++++++++++++++++++++++++++++++++++ */


/* +++ OBJECT METHODS +++ +++++++++++++++++++++++++++++++++++++++++++++++++++ */


    /**
     * Bereinigt die eingegebenen Berechnungsparameter aus dem Formular
     *
     * Leere Zeichenketten werden zu 0 und führende Nullen werden entfernt.
     *
     * @param       mixed   $value
     *              <br>Der Wert aus dem Formular
     *
     * @param       integer $minvalue
     *              <br>Standardmäßig ist der niedrigste, gültige Wert 0. Für den Fall, dass ein
     *              anderer Wert als Standarwert in das Eingabefeld eingesetzt werden soll, kann er
     *              hier angegeben werden.
     *
     * @return      integer Ein gültiger Integer-Wert.
     *
     * @version     1.0.0 / 2025-05-25
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    protected function _cleanupIntegerFormValue($value, $minvalue = 0)
    {
        $value = preg_replace('/[^0-9]/', '', $value);
        $length = strlen($value);

        switch ($length) {
            case 0:
                $value = $minvalue;
                break;

            case 1:
                $value = (int) $value;
                break;

            default:
                if ($value[0] === '0') {
                    $value = substr($value, 1);
                }
                $value = (int) $value;
        }
        if ($value < $minvalue) {
            $value = $minvalue;
        }
        return $value;

    } // _cleanupIntegerFormValue()


    /**
     * Blendet den Modal-Dialog aus
     *
     * @version     1.0.0 / 2025-05-25
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    public function hideModal()
    {
        $this->modalCaption = null;
        $this->modalMessage = null;
        $this->modalMethod =  null;
        $this->modalType = null;

        $this->modalVisibility = false;

    } // hideModal()


    /**
     * Zeigt einen Modal-Dialog an
     *
     * @param       string  $type
     *              <br>Der Typ des modalen Dialogfensters, das angezeigt werden soll.
     *              Als Übergabeparameter sollte eine der MODAL_TYPE__*-Konstanten verwendet werden.
     *
     * @param       string  $method
     *              <br>Der Name der Methode, die beim Klick auf den Button zur Bestätigung
     *              aufgerufen werden soll.
     *              Eine gleichnamige Methode muss in der Component-Klasse definiert sein.
     *
     * @param       string  $message
     *              <br>Die Meldung, die im Dialog angezeigt werden soll.
     *
     * @param       string  $caption
     *              <br>Eine Überschrift, die im Dialog angezeigt werden soll. Die Angabe dieses
     *              Parameters ist optional.
     *
     * @return      void
     *
     * @todo        - Gegebenenfalls könnte auch eine Standardüberschrift eingesetzt werden, wenn
     *                der Parameter $caption NULL ist. Durch die Übergabe von FALSE könnte die
     *                Verwendung der Standardüberschrift unterbunden werden.
     *                Bei der Implementierung dieses Features sollte eine eigene Locale-Datei für
     *                diese Klasse angelegt werden.
     *
     * @version     1.0.0 / 2025-05-25
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    public function showModal($type, $method, $message, $caption = null)
    {
        $this->_hideNotification();

        $this->modalCaption = $caption;
        $this->modalMessage = $message;
        $this->modalMethod = $method;
        $this->modalType = $type;

        $this->modalVisibility = true;

    } // showModal()


/* +++ CLASS METHODS +++ ++++++++++++++++++++++++++++++++++++++++++++++++++++ */


} // class FormComponentBase extends Component {}
