<?php

namespace AutoAdmin\Bundle\Content\Routing;

use AutoAdmin\Bundle\Content\Model\LocaleInterface;
use AutoAdmin\Bundle\Content\Translation\EntityTranslator;
use AutoAdmin\Bundle\Core\Helper\DoctrineHelper;
use Traversable;

class AutoRouterManager
{
    public function __construct(
        Traversable $guessers,
        protected EntityTranslator $translator,
        /* @var $routers array<ContentAutoRouterInterface> */
        protected array $routers = [],
        protected array $refs = [],
    ) {
        $this->routers = array_map([$this, 'addRouter'], iterator_to_array($guessers));
    }

    public function generate(
        ContentRouter $contentRouter,
        object $subject,
        ?string $route,
        array $parameters = [],
        array $options = []
    ) {
        $contentKey = $this->createKey($subject, $parameters['_locale'] ?? $this->translator->getLocale());
        if (array_key_exists($contentKey, $this->refs)) {
            return $this->refs[$contentKey];
        }

        $url = null;
        foreach ($this->routers as $router) {
            if ($router->supports($subject)) {
                $url = $router->buildUrl($contentRouter, $subject, $route, $parameters, $options);
                break;
            }
        }

        if ($subject && !empty($contentKey)) {
            $this->refs[$contentKey] = $url;
        }

        return $url;
    }

    protected function createKey(object $content, LocaleInterface|string $locale): string
    {
        // we were previously using "id and class" or "spl object id" for indexes but this wasn't working with object mutations,
        // also tried php serialize, wasn't doing good with closures
        // also tried symfony serializer, wasn't fast enough (probably too much info kept/processed)

        // We can now use mutations + cloning to generate multiple urls from one given object (cf. AL cocoons)

        return DoctrineHelper::getClass($content).'#'.$content->getId()
            .'~'.(string)$locale
            .'~'.spl_object_id($content);// permit to used "clone" to force cache ignoring
    }

    protected function addRouter(ContentAutoRouterInterface $router): ContentAutoRouterInterface
    {
        return $router;
    }
}
