<?php

namespace Planaday\Utility\DataFilters;

use Planaday\Utility\DataFilters\Validators\IsEmail;
use Planaday\Utility\DataFilters\Validators\IsHexColor;
use Planaday\Utility\DataFilters\Validators\IsTrue;
use Planaday\Utility\DataFilters\Validators\Needs;
use Planaday\Utility\DataFilters\Validators\NotEmpty;
use Planaday\Utility\DataFilters\Validators\NotNull;
use Planaday\Utility\DataFilters\Validators\Validator;

class AdvancedValidator {
	/** @var Validator[] */
	protected array $validations = [];

	/**
	 * @param mixed $data
	 * @param string $name
	 */
	public function __construct(
		protected mixed $data,
		protected string $name
	) {}

	public function validate(): array|bool{
		$errors = [];

		foreach ( $this->validations as $validation ) {
			$result = $validation->validate($this->data);
			if($result !== true) $errors[$validation->getName()] = $result;
		}

		if(empty($errors)) return true;

		return $errors;
	}

	public function clear(): void{
		$this->validations = [];
	}

	public function addValidation(Validator $validator):self {
		$this->validations[] = $validator;

		return $this;
	}

	public function getData(): mixed {
		return $this->data;
	}

	public function getName(): string {
		return $this->name;
	}

	/**
	 * @param AdvancedValidator $requirement
	 * @param bool|null $startCheckingAt if null, will always run. if false, will run if data !== null. if true, will run if data === true.
	 *
	 * @return AdvancedValidator validator that can be used to add validations to the needs validator
	 */
	public function needs(AdvancedValidator $requirement, ?bool $startCheckingAt = null):AdvancedValidator{
		$needs = new Needs($requirement, $this->data,  $startCheckingAt);

		$this->addValidation($needs);

		return $needs->getValidations();
	}

	public function isRequired(?string $message = null, ?bool $hasDefaultValue = false):self{
		$this->addValidation($message ? new NotEmpty($message) : new NotEmpty());
		if (!$hasDefaultValue) $this->addValidation($message ? new NotNull($message) : new NotNull());

		return $this;
	}

	public function isEmail(?string $message = null):self {
		$this->addValidation( $message ? new IsEmail( $message ) : new IsEmail() );

		return $this;
	}

	public function isTrue(?string $message = null):self {
		$this->addValidation( $message ? new IsTrue( $message ) : new IsTrue() );

		return $this;
	}

	public function isHexColor(?string $message = null):self {
		$this->addValidation( $message ? new IsHexColor( $message ) : new IsHexColor() );

		return $this;
	}
}