<?php declare(strict_types=1);

namespace Newland\NeosFiltering\Validation;

use Neos\Error\Messages\Error;
use Neos\Error\Messages\Result;
use Neos\Flow\ObjectManagement\ObjectManager;
use Neos\Flow\Annotations as Flow;

class BaseValidator implements FilterConfigurationValidator
{
    /** @var FilterConfigurationValidator[] */
    protected $validators;

    /** @var Result */
    protected $result;

    /**
     * @var ObjectManager
     * @Flow\Inject();
     */
    protected $objectManager;

    public function throwIfConfigurationInvalid(array $validatorClassNames, array $configuration): void
    {
        $result = $this->initialize($validatorClassNames)->validate($configuration, 'ROOT');

        if (!$result->hasErrors()) {
            return;
        }

        /** @var Error[][] $flattened */
        $flattened = $result->getFlattenedErrors();
        $errorMessages = [];
        foreach ($flattened as $property => $errors) {
            foreach ($errors as $error) {
                /** @var Error $error */
                $errorMessages[] = sprintf(
                    '- %s: %s',
                    $property,
                    $error->__toString()
                );
            }
        }
        throw new \InvalidArgumentException(
            sprintf(
                "Invalid filter configuration: \n%s",
                implode("\n", $errorMessages)
            )
        );
    }


    public function initialize(array $validators): self
    {
        $this->result = new Result();
        $this->validators = [];
        foreach ($validators as $validator) {
            if (\is_string($validator)) {
                /** @var FilterConfigurationValidator $validator */
                $validator = $this->objectManager->get($validator);
            }
            $this->validators[] = $validator;
        }

        return $this;
    }

    public function validate(array $configuration, string $path): Result
    {
        foreach ($this->validators as $validator) {
            $this->result->merge($validator->validate($configuration, $path));
        }

        return $this->result;
    }
}
