namespace Illuminate\Validation;

use Closure;
use DateTime;
use Countable;
use Exception;
use DateTimeZone;
use RuntimeException;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use BadMethodCallException;
use InvalidArgumentException;
use Illuminate\Support\Fluent;
use Illuminate\Support\MessageBag;
use Illuminate\Contracts\Container\Container;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Illuminate\Contracts\Validation\Validator as ValidatorContract;
// more namespace
class Validator implements ValidatorContract
{// class Validator implements ValidatorContract
    /**
     * The Translator implementation.
     *
     * @var \Symfony\Component\Translation\TranslatorInterface
     */
    protected $translator;//The Translator implementation

    /**
     * The Presence Verifier implementation.
     *
     * @var \Illuminate\Validation\PresenceVerifierInterface
     */
    protected $presenceVerifier;//The Presence Verifier implementation

    /**
     * The container instance.
     *
     * @var \Illuminate\Contracts\Container\Container
     */
    protected $container;// a instance about container

    /**
     * The failed validation rules.
     *
     * @var array
     */
    protected $failedRules = [];// The failed validation rules

    /**
     * The message bag instance.
     *
     * @var \Illuminate\Support\MessageBag
     */
    protected $messages;//The message bag instance.

    /**
     * The data under validation.
     *
     * @var array
     */
    protected $data;//The data under validation

    /**
     * The files under validation.
     *
     * @var array
     */
    protected $files = [];//The files under validation

    /**
     * The rules to be applied to the data.
     *
     * @var array
     */
    protected $rules;//The rules to be applied to the data

    /**
     * All of the registered "after" callbacks.
     *
     * @var array
     */
    protected $after = [];//All of the registered "after" callbacks

    /**
     * The array of custom error messages.
     *
     * @var array
     */
    protected $customMessages = [];//The array of custom error messages.

    /**
     * The array of fallback error messages.
     *
     * @var array
     */
    protected $fallbackMessages = [];//The array of fallback error messages.

    /**
     * The array of custom attribute names.
     *
     * @var array
     */
    protected $customAttributes = [];// The array of custom attribute names.

    /**
     * The array of custom displayabled values.
     *
     * @var array
     */
    protected $customValues = [];//The array o custom displayabled values.

    /**
     * All of the custom validator extensions.
     *
     * @var array
     */
    protected $extensions = [];// All of the custom validator extensions

    /**
     * All of the custom replacer extensions.
     *
     * @var array
     */
    protected $replacers = [];// All of the custom replacer extensions.

    /**
     * The size related validation rules.
     *
     * @var array
     */
    protected $sizeRules = ['Size', 'Between', 'Min', 'Max'];// The size related validation rules.

    /**
     * The numeric related validation rules.
     *
     * @var array
     */
    protected $numericRules = ['Numeric', 'Integer'];//The numeric related validation rules.

    /**
     * The validation rules that imply the field is required.
     *
     * @var array
     */
    protected $implicitRules = [
        'Required', 'RequiredWith', 'RequiredWithAll', 'RequiredWithout', 'RequiredWithoutAll',
        'RequiredIf', 'RequiredUnless', 'Accepted',
        // 'Array', 'Boolean', 'Integer', 'Numeric', 'String',
    ];// The validation rules that imply the field is required.

    /**
     * The validation rules which depend on other fields as parameters.
     *
     * @var array
     */
    protected $dependentRules = [
        'RequiredWith', 'RequiredWithAll', 'RequiredWithout', 'RequiredWithoutAll',
        'RequiredIf', 'RequiredUnless', 'Confirmed', 'Same', 'Different',
    ];//The validation rules which depend on other fields as parameters.

    /**
     * Create a new Validator instance.
     *
     * @param  \Symfony\Component\Translation\TranslatorInterface  $translator
     * @param  array  $data
     * @param  array  $rules
     * @param  array  $messages
     * @param  array  $customAttributes
     * @return void
     */
    public function __construct(TranslatorInterface $translator, array $data, array $rules, array $messages = [], array $customAttributes = [])
    {// parameters is more
        $this->translator = $translator;
        $this->customMessages = $messages;
        $this->data = $this->parseData($data);
        $this->customAttributes = $customAttributes;// set parameters

        // Explode the rules first so that the implicit ->each calls are made...
        $rules = $this->explodeRules($rules);// get rules from the $ rules

        $this->rules = array_merge((array) $this->rules, $rules);// array_merge
    }// Create a new Validator messages

    /**
     * Parse the data and hydrate the files array.
     *
     * @param  array   $data
     * @param  string  $arrayKey
     * @return array
     */
    protected function parseData(array $data, $arrayKey = null)
    {
        if (is_null($arrayKey)) {
            $this->files = [];//set the value  array
        }//parseData data
       // no arrayKey no return

        foreach ($data as $key => $value) {
            $key = ($arrayKey) ? "$arrayKey.$key" : $key;// get this key

            // If this value is an instance of the HttpFoundation File class we will
            // remove it from the data array and add it to the files array, which
            // we use to conveniently separate out these files from other data.
            if ($value instanceof File) {// determine this values
                $this->files[$key] = $value;// change this

                unset($data[$key]);// delete this $key
            } elseif (is_array($value)) {
                $this->parseData($value, $key);
            }// parse Data
        }

        return $data;
    }//

    /**
     * Explode the rules into an array of rules.
     *
     * @param  string|array  $rules
     * @return array
     */
    protected function explodeRules($rules)
    {
        foreach ($rules as $key => $rule) {
            if (Str::contains($key, '*')) {
                $this->each($key, [$rule]);

                unset($rules[$key]);
            } else {
                $rules[$key] = (is_string($rule)) ? explode('|', $rule) : $rule;
            }// a lot of rules
        }// rules as

        return $rules;// rules
    }//Explode