<?php
  /**
   * @version     1.0.0
   * @package     Joomla 4
   * @subpackage  Formea
   * @author      Feseur Sdn Bhd
   * @copyright   Copyright (C) 2010-2023 Feseur Sdn Bhd. All rights reserved.
   * @license     GNU General Public License version 2 or later;
   */


  defined('_JEXEC') or die();

  // no direct access
  use Feseur\Library\FsrResponse;
  use Joomla\CMS\Language\Text;
  use Joomla\Component\Formea\Site\Libraries\FormeaValidation;

  class AlphanumericValidation extends FormeaValidation
  {

    public function __construct($config)
    {
      parent::__construct($config);
    }

    public function validate()
    {
      $retObject       = new FsrResponse();
      $submitted_value = preg_replace('/\s+/', '', $this->submitted_value);
      $result          = (object) [
        'hasError' => false,
        'msg'      => ''
      ];


      if (!empty($this->validation))
      {
        $validator  = $this->validation['validator'];
        $conditions = $this->validation['conditions'];
        $hasError   = false;

        if($validator == 'Numbers'){
          if (isset($conditions->numcheck->num) && !$hasError)
          {
            $submitted_value = (float) $submitted_value;
            $hasError        = true;

            foreach ($conditions->numcheck->num as $numCondition)
            {

              $targetValue = (float) $numCondition->val;
              $operator    = $numCondition->operator;

              switch ($operator)
              {
                case '>':
                  $hasError = $submitted_value <= $targetValue;
                  break;
                case '==':
                  $hasError = $submitted_value != $targetValue;
                  break;
                case '!=':
                  $hasError = $submitted_value == $targetValue;
                  break;
                case '<':
                  $hasError = $submitted_value >= $targetValue;
                  break;
                case 'lte':
                  $hasError = $submitted_value > $targetValue;
                  break;
                case '>=':
                  $hasError = $submitted_value < $targetValue;
                  break;
              }

              if ($hasError)
              {
                break;
              }
            }
          }
        }elseif ($validator == 'Alphabets'){
          if ((isset($conditions->char_length->length) || isset($conditions->char->string)) && !$hasError)
          {
            $submitted_value = (string) $submitted_value;

            if (!$this->isValidAlphabeticString($submitted_value))
            {
              $hasError = true;
            }

            if (isset($conditions->char_length->length) && !$hasError)
            {
              $submitted_value = (string) $submitted_value;
              $hasError        = true;

              foreach ($conditions->char_length->length as $numCondition)
              {

                $targetValue = (float) $numCondition->val;
                $operator    = $numCondition->operator;

                switch ($operator)
                {
                  case '>':
                    $hasError = strlen($submitted_value) <= $targetValue;
                    break;
                  case '==':
                    $hasError = strlen($submitted_value) != $targetValue;
                    break;
                  case '!=':
                    $hasError = strlen($submitted_value) == $targetValue;
                    break;
                  case '<':
                    $hasError = strlen($submitted_value) >= $targetValue;
                    break;
                  case 'lte':
                    $hasError = strlen($submitted_value) > $targetValue;
                    break;
                  case '>=':
                    $hasError = strlen($submitted_value) < $targetValue;
                    break;
                }

                if ($hasError)
                {
                  break;
                }
              }
            }

            if (isset($conditions->char->string) && !$hasError)
            {
              $submitted_value = (string) $submitted_value;
              $hasError        = true;

              foreach ($conditions->char->string as $numCondition)
              {

                $targetValue = (string) $numCondition->val;
                $operator    = $numCondition->operator;

                switch ($operator)
                {
                  case '==':
                    $hasError = $submitted_value != $targetValue;
                    break;
                  case '!=':
                    $hasError = $submitted_value == $targetValue;
                    break;
                  case 'contains':
                    // Error if submitted value does  contain targetValue
                    $hasError = strpos($submitted_value, $targetValue) == false;
                    break;
                  case '!contains':
                    // Error if submitted value does not contain targetValue
                    $hasError = strpos($submitted_value, $targetValue) !== false;
                    break;
                }

                if ($hasError)
                {
                  break;
                }
              }
            }

          }
        }elseif ($validator == 'Alphanumeric'){
          if ((isset($conditions->ap_char_length->length) || isset($conditions->ap_char->string)) && !$hasError)
          {
            $submitted_value = (string) $submitted_value;

            if (!$this->isValidAlphanumericString($submitted_value))
            {
              $hasError = true;
            }

            if (isset($conditions->ap_char_length->length) && !$hasError)
            {
              $submitted_value = (string) $submitted_value;
              $hasError        = true;

              foreach ($conditions->ap_char_length->length as $numCondition)
              {

                $targetValue = (float) $numCondition->val;
                $operator    = $numCondition->operator;

                switch ($operator)
                {
                  case '>':
                    $hasError = strlen($submitted_value) <= $targetValue;
                    break;
                  case '==':
                    $hasError = strlen($submitted_value) != $targetValue;
                    break;
                  case '!=':
                    $hasError = strlen($submitted_value) == $targetValue;
                    break;
                  case '<':
                    $hasError = strlen($submitted_value) >= $targetValue;
                    break;
                  case 'lte':
                    $hasError = strlen($submitted_value) > $targetValue;
                    break;
                  case '>=':
                    $hasError = strlen($submitted_value) < $targetValue;
                    break;
                }

                if ($hasError)
                {
                  break;
                }
              }
            }

            if (isset($conditions->ap_char->string) && !$hasError)
            {
              $submitted_value = (string) $submitted_value;
              $hasError        = true;

              foreach ($conditions->ap_char->string as $numCondition)
              {

                $targetValue = (string) $numCondition->val;
                $operator    = $numCondition->operator;

                switch ($operator)
                {
                  case '==':
                    $hasError = $submitted_value != $targetValue;
                    break;
                  case '!=':
                    $hasError = $submitted_value == $targetValue;
                    break;
                  case 'contains':
                    // Error if submitted value does  contain targetValue
                    $hasError = strpos($submitted_value, $targetValue) == false;
                    break;
                  case '!contains':
                    // Error if submitted value does not contain targetValue
                    $hasError = strpos($submitted_value, $targetValue) !== false;
                    break;
                }

                if ($hasError)
                {
                  break;
                }
              }
            }

          }
        }






        if ($hasError)
        {
          $msg = Text::_('COM_FORMEA_INVALID_INPUT');
          if (!empty($this->validation) && isset($this->validation['invalid_msg']))
          {
            if (isset($this->validation['invalid_msg'][$this->langTag]))
            {
              $msg = Text::_($this->validation['invalid_msg'][$this->langTag]);
            }
            else
            {
              $arr      = array_values($this->validation['invalid_msg']);
              $totalArr = count($arr);
              for ($i = 0; $i < $totalArr; $i++)
              {
                if (!empty($arr[$i]))
                {
                  $msg = Text::_($arr[$i]);
                  break;
                }
              }
            }
          }
          $result->hasError = true;
          $result->msg      = $msg;
        }
      }
      $retObject->setSuccess(true);
      $retObject->setResult($result);

      return $retObject;
    }

    /**
     * This regular expression will match strings that contain only alphabets, accented characters, and letters from various languages including Arabic and Chinese
     * @param $string
     *
     * @return false|int
     *
     * @since version
     */
    protected function isValidAlphabeticString($string)
    {
      return preg_match('/^[\p{L}\p{M}]+$/u', $string);
    }

    /**
     * This regular expression will match strings that contain only alphabets, accented characters, and numbers
     * @param $string
     *
     * @return false|int
     *
     * @since 1.0.0
     */
    protected function isValidAlphanumericString($string)
    {
      return preg_match('/^[\p{L}\p{M}\p{N}]+$/u', $string);
    }
  }
