<?php

namespace AutoAdmin\Bundle\Admin\Form\TypeGuesser;

use AutoAdmin\Bundle\Admin\Attribute\Loader\AttributeLoader;
use Traversable;

class TypeGuesserManager
{
    protected AttributeLoader $attributeLoader;

    /**
     * @var array<AdminTypeGuesserInterface>
     */
    protected array $guessers;

    public function __construct(AttributeLoader $attributeLoader, Traversable $guessers)
    {
        $this->attributeLoader = $attributeLoader;
        $this->guessers = array_map([$this, 'addGuesser'], iterator_to_array($guessers));

        usort($this->guessers, function (AdminTypeGuesserInterface $a, AdminTypeGuesserInterface $b) {
            return $a->priority() <=> $b->priority();
        });
    }

    public function guess(array $propertyConfig, string $class, string $property): ?AdminTypeGuess
    {
        $type = $propertyConfig['type'] ?? null;
        $typeOptions = $propertyConfig['type_options'] ?? [];

        if (!empty($type) && is_string($type) && class_exists($type)) {
            return new AdminTypeGuess($type, $typeOptions);
        }

        /** @var AdminTypeGuesserInterface $guesser */
        foreach ($this->guessers as $guesser) {
            if ($guesser->supportStringType($propertyConfig)) {
                return new AdminTypeGuess(
                    $guesser->getFormType(),
                    array_merge(
                        $guesser->getDefaultFormTypeOptions(),
                        $typeOptions
                    )
                );
            }
        }

        /** @var AdminTypeGuesserInterface $guesser */
        foreach ($this->guessers as $guesser) {
            if ($guesser->supportPropertyType($class, $property)) {
                return new AdminTypeGuess(
                    $guesser->getFormType(),
                    array_merge(
                        $guesser->getDefaultFormTypeOptions(),
                        $typeOptions
                    )
                );
            }
        }

        return null;
    }

    protected function addGuesser(AdminTypeGuesserInterface $guesser): AdminTypeGuesserInterface
    {
        return $guesser;
    }
}
