<?php

namespace AutoAdmin\Bundle\Admin\Attribute\Loader;

use AutoAdmin\Bundle\Admin\Attribute\ClassAttributes;
use AutoAdmin\Bundle\Admin\Attribute\PropertyAttributes;
use Exception;
use InvalidArgumentException;
use ReflectionClass;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\Config\Loader\LoaderResolverInterface;

class AttributeLoader implements LoaderInterface
{
    /**
     * Loads a resource.
     *
     * @throws Exception If something went wrong
     */
    public function load($class, string $type = null): ClassAttributes
    {
        if (!class_exists($class)) {
            throw new InvalidArgumentException(sprintf('Class "%s" does not exist.', $class));
        }

        $refl = new ReflectionClass($class);
        if ($refl->isAbstract()) {
            throw new InvalidArgumentException(
                sprintf('Attributes from class "%s" cannot be read as it is abstract.', $refl->getName())
            );
        }

        $attributes = [];

        foreach ($refl->getProperties() as $property) {
            $indexedAttributes = [];

            foreach ($property->getAttributes() as $propertyAttributes) {
                $index = $propertyAttributes->getName();
                if (isset($indexedAttributes[$index])) {
                    throw new Exception(
                        sprintf(
                            'Attribute loader encountered a duplicated attribute in class "%s" on field "%s".',
                            $class,
                            $property->getName()
                        )
                    );
                }
                $indexedAttributes[$index] = $propertyAttributes->getArguments();
            }

            $attributes[$property->getName()] = new PropertyAttributes($class, $indexedAttributes);
        }

        return new ClassAttributes($attributes);
    }

    /**
     * Returns whether this class supports the given resource.
     *
     * @return bool True if this class supports the given resource, false otherwise
     */
    public function supports($class, ?string $type = null): bool
    {
        return substr($class, -11) === 'Translation';
    }

    /**
     * Gets the loader resolver.
     */
    public function getResolver(): LoaderResolverInterface
    {
        // not needed
    }

    /**
     * Sets the loader resolver.
     */
    public function setResolver(LoaderResolverInterface $resolver): void
    {
        // not needed
    }

    protected function findAttribute($propertyAttributes, $searched = null)
    {
        if ($searched === null) {
            return null;
        }

        return array_values(
                array_filter(
                    $propertyAttributes,
                    function ($propertyAttribute) use ($searched) {
                        return get_class($propertyAttribute) === $searched;
                    }
                )
            )[0] ?? null;
    }
}
