<?php

declare(strict_types=1);

/*
 * This file is part of the Ferienpass package.
 *
 * (c) Richard Henkenjohann <richard@ferienpass.online>
 *
 * For more information visit the project website <https://ferienpass.online>
 * or the documentation under <https://docs.ferienpass.online>.
 */

namespace Ferienpass\AdminBundle\Form\Extension\Form;

use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class SectionExtension extends AbstractTypeExtension
{
    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefined('display_section');
        $resolver->addAllowedTypes('display_section', ['null', 'string']);
        $resolver->setDefaults([
            'display_section' => null,
        ]);
    }

    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        if (!$options['display_section']) {
            return;
        }

        $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($options) {
            $this->removeAllFormsElementsNotMatching($event->getForm(), $options['display_section']);
        }, -10);
    }

    public static function getExtendedTypes(): iterable
    {
        return [
            \Ferienpass\AdminBundle\Form\EditAccountType::class,
            \Ferienpass\AdminBundle\Form\EditEditionType::class,
            \Ferienpass\AdminBundle\Form\EditHostType::class,
            \Ferienpass\AdminBundle\Form\EditOfferType::class,
            \Ferienpass\AdminBundle\Form\PersonalDataType::class,
            \Ferienpass\AdminBundle\Form\EditParticipantType::class,
        ];
    }

    private function removeAllFormsElementsNotMatching(FormInterface $form, string $display): void
    {
        foreach ($form->all() as $name => $formElement) {
            if (($section = $formElement->getConfig()->getOption('section')) && $display !== $section) {
                $form->remove($name);
            }
        }
    }
}
