<?php

namespace Helpers\Validator;

use Exception;
use Helpers\Trad\ITrad;
use Helpers\Trad\Trad;
use Modules\Reception\Service\ValidatorReceptionService;
use Psr\Container\ContainerInterface;

class Validator
{
    protected int $validate = 0;
    protected string $error = '';

    /**
     * @var int
     */
    protected $nonBloquant = 0;
    /**
     * @var string
     */
    protected $errorNonBloquant = '';
    
    protected ?ITrad $trad;
    /**
     * errorTable
     *
     * @var array<mixed>
     */
    protected $errorTable = [];
    protected \PDO $pdo;
    /** @var array<mixed> */
    protected $listeValueEntite = [];
    /** @var array<mixed> */
    protected $listeValue = [];

    private ?ContainerInterface $container;

    /**
     * contenaire
     *
     * @var array<mixed>
     */
    protected $contenaire = [];

    /**
     * Validator Globale
     */
    use \Traits\Validator\Chaine;
    use \Traits\Validator\Date;
    use \Traits\Validator\IntegerValidator;
    use \Traits\Validator\Contains;
    use \Traits\Validator\Floats;
    use \Traits\Validator\Zoom;
    use \Traits\Validator\Checkbox;
    use \Traits\Validator\File;
    use \Traits\Validator\ValidatorEntity;
    use \Traits\Validator\Heure;
    use \Traits\Validator\ValidatorChampSupp;
    use \Traits\Validator\Iban;
    use \Traits\Validator\CaracCompl;
    use \Traits\Validator\RawSqlValidator;
    use \Traits\Validator\EnumValidator;

    /**
     * Validator Modules
     */
    use \Traits\Validator\Commande\ValidatorCommandeService;
    use ValidatorReceptionService;


    /**
     * @param ContainerInterface $container is required for zoom using OxaDW
     */
    public function __construct(\PDO $pdo, ITrad $trad, ?ContainerInterface $container = null)
    {
        $this->pdo = $pdo;
        $this->trad = $trad;
        $this->container = $container;
    }
    
    /**
     * isValid
     * retourne faux si le $this->error est rempli.
     *
     * @param  bool $forceNonBloquant
     * @return bool
     */
    public function isValid($forceNonBloquant = false) : bool
    {
        if ($this->validate != 0 || ($this->nonBloquant != 0 && $forceNonBloquant==false)) {
            return false;
        } else {
            return true;
        }
    }

    /**
    * retourne faux si le $this->nonBloquant est rempli.
    * @return bool
    */
    public function isNonBloquant() : bool
    {
        if ($this->nonBloquant != 0 && $this->validate == 0) {
            return true;
        } else {
            return false;
        }
    }

    /**
    * Retourne les erreurs du validator
    * @return string
    */
    public function getError()
    {
        return $this->error;
    }

    
    public function getErrorJson() :string
    {
        $s = $this->error;
        // TODO : supprimer tout les br ?

        // suppression du premier saut de ligne
        if (strpos($s, '<br />') === 0) {
            $s = substr($s, 6);
        }

        return $s;
    }

    /**
    * Retourne les erreurs du validator
    * @return string
    */
    public function getErrorNonBloquant(bool $tooltips = false)
    {
        if ($tooltips) {
            $text = '#NB#'.$this->errorNonBloquant;
        } else {
            $text = $this->errorNonBloquant;
        }
        return $text;
    }
    /**
     * Verifie que la taille d'un champs est respecté
     * @param string $value
     * @param string $nomChamp
     * @param number $sizeMin
     * @param number $sizeMax
     * @return bool
     */
    public function size($value, $nomChamp, $sizeMin = 0, $sizeMax = 0) : bool
    {
        if (mb_strlen($value, 'utf8') > $sizeMax || mb_strlen($value, 'utf8') < $sizeMin) {
            $this->validate += 1 ;
            $this->error .= '<br />'.\Helpers\Trad\Trad::strBuild(
                $this->getTrad()->t('Le champ @1@ doit comporter @2@ à @3@ caractères.'),
                $nomChamp,
                $sizeMin,
                $sizeMax
            );
            return false;
        }
        return true;
    }

    /**
    * Fonction ajoutant manuellement une erreur au validator.
    *
    * @param string $message
    */
    public function setError($message) :bool
    {
        $this->validate += 1 ;
        $this->error .= '<br />' . $message;
    
        return false;
    }

        /**
    * Fonction ajoutant manuellement une erreur au validator.
    *
    * @param string $message
    * @return bool
    */
    public function setErrorNonBloquant($message)
    {
        $this->nonBloquant += 1 ;
        $this->errorNonBloquant .= '<br />' . $message;
    
        return false;
    }

    /**
     * setValueError
     *
     * @param mixed $mixed
     * @return bool
     */
    public function setValueError($mixed)
    {
        $this->validate += 1;
        $br = '<br />';
        if (\is_string($mixed)) {
            if (\strpos(str_replace(' ', '', $mixed), '<br/>') !== false) {
                $br = '';
            }
            $this->error .= $br.$mixed;
        } elseif (\is_array($mixed)) {
            $this->errorTable[] = $mixed;
            $trad = $this->getTrad();
            if ($mixed[1] == true) {
                $this->error .= $br . Trad::strBuild($trad->t('L\'erreur "@1@" est bloquante.'), $mixed[0]);
            } else {
                $this->error .= $br . Trad::strBuild($trad->t('L\'erreur "@1@" n\'est pas bloquante.'), $mixed[0]);
            }
        }
        return false;
    }
    
    /**
     * getContenaire
     *
     * @return array<mixed>
     */
    public function getContenaire()
    {
        return $this->contenaire;
    }

    public function getTrad() :ITrad
    {
        return $this->trad;
    }
    public function getPdo() :\PDO
    {
        return $this->pdo;
    }

    public function getContainer() :ContainerInterface
    {
        if ($this->container == null) {
            throw new \Exception('Missing container');
        }
        return $this->container;
    }
}
