<?php

/**
 * Lifestyle Webconsulting GmbH
 *
 * LICENSE: This Software is the property of Lifestyle Webconsulting GmbH (Aschaffenburg, Germany)
 * and is private by copyright law - it is NOT Freeware.
 *
 * Any unauthorized use of this software without a valid license
 * is a violation of the license agreement and will be prosecuted by
 * civil and criminal law.
 *
 * @copyright  2018 Lifestyle Webconsulting GmbH
 * @link       http://www.life-style.de
 */


namespace Sso\BackendBundle\Form;

use Sso\BackendBundle\Model\Form\Application as ApplicationFormModel;
use Sso\BackendBundle\Model\Form\ApplicationAttributeOption;
use Sso\WebserviceBundle\Entity\Webservice\Type\Application;
use Sso\WebserviceBundle\Entity\Webservice\Type\AttributeOption;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\CallbackTransformer;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

/**
 * Class WsApplicationAttributeType
 *
 * @copyright  2016 Lifestyle Webconsulting GmbH
 * @link       http://www.life-style.de
 * @package    Sso\BackendBundle\Form
 */
class WsApplicationAttributeType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('Name');
        $builder->add('Type', ChoiceType::class, [
            'choices' => [
                "one" => "One",
                "many" => "Many",
            ],
        ]);
        $builder->add('displayType', ChoiceType::class, [
            'required' => false,
            'choices' => [
                "input" => "Text Input (default)",
                "datepicker" => "Datepicker",
                "dropdown" => "Dropdown",
            ],
        ]);
        $builder->add('attributeOptions', CollectionType::class, [
            'required' => false,
            'allow_add' => true,
            'allow_delete' => true,
            'delete_empty' => true,
            'entry_options' => ['label' => false],
            'entry_type' => WsApplicationAttributeOptionType::class,
            'attr' => ['class' => 'form-collection'],
        ]);
        $builder->add('Application', EntityType::class, [
            'class' => Application::class,
            'property' => 'Name',
        ]);

        $builder->get('attributeOptions')
            ->addModelTransformer(new CallbackTransformer(
                function ($optionsAsArray) {
                    $options = [];
                    // We don't receive an assoc array as expected because our
                    // event listener below has already transformed the data
                    foreach ($optionsAsArray ?? [] as $data) {
                        $options[] = ApplicationAttributeOption::create($data['label'], $data['value']);
                    }
                    return 0 < count($options) ? $options : null;
                },
                function ($optionsAsObjects) {
                    $options = [];
                    foreach ($optionsAsObjects ?? [] as $option) {
                        $options[$option->getLabel()] = $option->getValue();
                    }
                    return 0 < count($options) ? $options : null;
                }
            ))
            ->addEventListener(
                FormEvents::PRE_SET_DATA,
                function (FormEvent $event) {
                    $options = [];
                    // As Symfony has some problems to use any string as property_path
                    // move label into an array and use numeric index for data array
                    foreach ($event->getData() ?? [] as $label => $value) {
                        $options[] = array(
                            'label' => $label,
                            'value' => $value
                        );
                    }
                    $event->setData(0 < count($options) ? $options : null);
                },
                1 // Priority higher than Symfonys default event listener
            );
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(['data_class' => 'Sso\WebserviceBundle\Entity\Webservice\Type\Attribute']);
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'sso_backendbundle_webserviceapplicationattributes';
    }

    /**
     * @param FormView $view
     * @param FormInterface $form
     * @param array $options
     */
    public function finishView(FormView $view, FormInterface $form, array $options)
    {
        // Sort application-select-options
        usort($view->children['Application']->vars['choices'], [ApplicationFormModel::class, 'compare']);
    }
}
