<?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\CustomFieldsBundle\Form\Type;

use Chill\MainBundle\Templating\TranslatableStringHelper;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormInterface;

/**
 * This type create a Choice field with custom fields as choices.
 *
 * This type can only be associated with a customFieldsGroup type. The field
 * is populated when the data (a customFieldsGroup entity) is associated with
 * the form
 */
class LinkedCustomFieldsType extends AbstractType
{
    /**
     * The name for the choice field.
     *
     * Extracted from builder::getName
     */
    private string $choiceName = 'choice';

    /**
     * the option of the form.
     *
     * @internal options are stored at the class level to be reused by appendChoice, after data are setted
     */
    private array $options = [];

    public function __construct(private readonly TranslatableStringHelper $translatableStringHelper) {}

    /**
     * append Choice on POST_SET_DATA event.
     *
     * Choices are extracted from custom_field_group (the data associated
     * with the root form)
     *
     * @return void
     */
    public function appendChoice(FormEvent $event)
    {
        $rootForm = $this->getRootForm($event->getForm());
        $group = $rootForm->getData();

        if (null === $group) {
            return;
        }

        $choices = [];

        foreach ($group->getCustomFields() as $customFields) {
            $choices[$customFields->getSlug()] =
                    $this->translatableStringHelper
                        ->localize($customFields->getName());
        }

        $options = array_merge($this->options, [
            'choices' => $choices,
        ]);

        $event->getForm()->getParent()->add(
            $this->choiceName,
            ChoiceType::class,
            $options
        );
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $this->choiceName = $builder->getName();
        $this->options = $options;

        $builder->addEventListener(
            FormEvents::POST_SET_DATA,
            $this->appendChoice(...)
        );
    }

    public function getBlockPrefix()
    {
        return 'custom_fields_group_linked_custom_fields';
    }

    public function getParent()
    {
        return ChoiceType::class;
    }

    /**
     * Return the root form (i.e. produced from CustomFieldsGroupType::getForm).
     *
     * @return FormInterface
     */
    private function getRootForm(FormInterface $form)
    {
        if (null === $form->getParent()) {
            return $form;
        }

        return $this->getRootForm($form->getParent());
    }
}
