<?php

declare(strict_types=1);

/*
 * Chill is a software for social workers
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Chill\EventBundle\Templating\Entity;

use Chill\EventBundle\Entity\EventTheme;
use Chill\MainBundle\Templating\Entity\ChillEntityRenderInterface;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Symfony\Contracts\Translation\TranslatorInterface;
use Twig\Error\LoaderError;
use Twig\Error\RuntimeError;
use Twig\Error\SyntaxError;

/**
 * @implements ChillEntityRenderInterface<EventTheme>
 */
class EventThemeRender implements ChillEntityRenderInterface
{
    public const AND_CHILDREN_MENTION = 'show_and_children_mention';

    public const DEFAULT_ARGS = [
        self::SEPARATOR_KEY => ' > ',
        self::SHOW_AND_CHILDREN => false,
        self::AND_CHILDREN_MENTION => 'event_theme.and children',
    ];

    public const SEPARATOR_KEY = 'default.separator';

    /**
     * Show a mention "and children" on each EventTheme, if the event theme
     * has at least one child.
     */
    public const SHOW_AND_CHILDREN = 'show_and_children';

    public function __construct(private readonly TranslatableStringHelper $translatableStringHelper, private readonly \Twig\Environment $engine, private readonly TranslatorInterface $translator) {}

    /**
     * @throws RuntimeError
     * @throws SyntaxError
     * @throws LoaderError
     */
    public function renderBox($entity, array $options): string
    {
        $options = array_merge(self::DEFAULT_ARGS, $options);
        // give some help to twig: an array of parents
        $parents = $this->buildParents($entity);

        return $this
            ->engine
            ->render(
                '@ChillEvent/Entity/event_theme.html.twig',
                [
                    'eventTheme' => $entity,
                    'parents' => $parents,
                    'options' => $options,
                ]
            );
    }

    public function renderString($entity, array $options): string
    {
        /** @var EventTheme $entity */
        $options = array_merge(self::DEFAULT_ARGS, $options);

        $titles = [$this->translatableStringHelper->localize($entity->getName())];

        // loop to parent, until root
        while ($entity->hasParent()) {
            $entity = $entity->getParent();
            $titles[] = $this->translatableStringHelper->localize(
                $entity->getName()
            );
        }

        $titles = \array_reverse($titles);

        $title = \implode($options[self::SEPARATOR_KEY], $titles);

        if ($options[self::SHOW_AND_CHILDREN] && $entity->hasChildren()) {
            $title .= ' ('.$this->translator->trans($options[self::AND_CHILDREN_MENTION]).')';
        }

        return $title;
    }

    public function supports($entity, array $options): bool
    {
        return $entity instanceof EventTheme;
    }

    private function buildParents(EventTheme $entity): array
    {
        $parents = [];

        while ($entity->hasParent()) {
            $entity = $parents[] = $entity->getParent();
        }

        return $parents;
    }
}
