<?php

namespace Lc\SovBundle\Controller;

use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\QueryBuilder;
use EasyCorp\Bundle\EasyAdminBundle\Collection\ActionCollection;
use EasyCorp\Bundle\EasyAdminBundle\Collection\EntityCollection;
use EasyCorp\Bundle\EasyAdminBundle\Collection\FieldCollection;
use EasyCorp\Bundle\EasyAdminBundle\Collection\FilterCollection;
use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
use EasyCorp\Bundle\EasyAdminBundle\Config\Actions;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Config\KeyValueStore;
use EasyCorp\Bundle\EasyAdminBundle\Config\Option\EA;
use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext;
use EasyCorp\Bundle\EasyAdminBundle\Contracts\Controller\CrudControllerInterface;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController as EaAbstractCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto;
use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto;
use EasyCorp\Bundle\EasyAdminBundle\Dto\SearchDto;
use EasyCorp\Bundle\EasyAdminBundle\Event\AfterCrudActionEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\AfterEntityUpdatedEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeCrudActionEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeEntityDeletedEvent;
use EasyCorp\Bundle\EasyAdminBundle\Exception\ForbiddenActionException;
use EasyCorp\Bundle\EasyAdminBundle\Exception\InsufficientEntityPermissionException;
use EasyCorp\Bundle\EasyAdminBundle\Factory\ControllerFactory;
use EasyCorp\Bundle\EasyAdminBundle\Factory\EntityFactory;
use EasyCorp\Bundle\EasyAdminBundle\Factory\FilterFactory;
use EasyCorp\Bundle\EasyAdminBundle\Factory\PaginatorFactory;
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
use EasyCorp\Bundle\EasyAdminBundle\Field\FormField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextareaField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use EasyCorp\Bundle\EasyAdminBundle\Provider\AdminContextProvider;
use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator;
use EasyCorp\Bundle\EasyAdminBundle\Security\Permission;
use Lc\CaracoleBundle\Controller\Order\OrderShopAdminController;
use Lc\SovBundle\Component\EntityComponent;
use Lc\SovBundle\Container\ComponentContainer;
use Lc\SovBundle\Container\File\FileContainer;
use Lc\SovBundle\Container\Newsletter\NewsletterContainer;
use Lc\SovBundle\Container\Reminder\ReminderContainer;
use Lc\SovBundle\Container\Setting\SiteSettingContainer;
use Lc\SovBundle\Container\Site\NewsContainer;
use Lc\SovBundle\Container\Site\PageContainer;
use Lc\SovBundle\Container\Site\SiteContainer;
use Lc\SovBundle\Container\Ticket\TicketContainer;
use Lc\SovBundle\Container\Ticket\TicketMessageContainer;
use Lc\SovBundle\Container\User\GroupUserContainer;
use Lc\SovBundle\Container\User\UserContainer;
use Lc\SovBundle\Doctrine\Extension\DevAliasInterface;
use Lc\SovBundle\Doctrine\Extension\SeoInterface;
use Lc\SovBundle\Doctrine\Extension\SortableInterface;
use Lc\SovBundle\Doctrine\Extension\TranslatableInterface;
use Lc\SovBundle\Doctrine\Extension\TreeInterface;
use Lc\SovBundle\Field\CollectionField;
use Lc\SovBundle\Field\Filter\FilterManager;
use Lc\SovBundle\Form\Common\FiltersFormType;
use Lc\SovBundle\Form\Common\PositionType;
use Lc\SovBundle\Translation\TranslatorAdmin;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;
use Symfony\Component\HttpFoundation\Session\SessionInterface;


abstract class AbstractAdminController extends EaAbstractCrudController
{
    protected FormInterface $filtersForm;

    public static function getSubscribedServices()
    {
        return array_merge(
                parent::getSubscribedServices(),
                [
                        TranslatorAdmin::class => TranslatorAdmin::class,
                        SessionInterface::class => SessionInterface::class,
                        RequestStack::class => RequestStack::class,
                        EntityManagerInterface::class => EntityManagerInterface::class,
                        FilterManager::class => FilterManager::class,
                        ComponentContainer::class => ComponentContainer::class,
                        FileContainer::class => FileContainer::class,
                        NewsletterContainer::class => NewsletterContainer::class,
                        ReminderContainer::class => ReminderContainer::class,
                        NewsContainer::class => NewsContainer::class,
                        PageContainer::class => PageContainer::class,
                        SiteContainer::class => SiteContainer::class,
                        TicketContainer::class => TicketContainer::class,
                        TicketMessageContainer::class => TicketMessageContainer::class,
                        GroupUserContainer::class => GroupUserContainer::class,
                        UserContainer::class => UserContainer::class,
                        SiteSettingContainer::class => SiteSettingContainer::class,
                ]
        );
    }


    public function configureResponseParameters(KeyValueStore $responseParameters): KeyValueStore
    {
        if ($responseParameters->get('global_actions')) {
            $this->overrideGlobalActions($responseParameters->get('global_actions'));
        }
        if ($responseParameters->get('entities')) {
            $this->overrideEntitiesActions($responseParameters->get('entities'));
        }
        if (Crud::PAGE_INDEX === $responseParameters->get('pageName')) {
            $responseParameters->set('fields', $this->configureFields('index'));

            if ($this->filtersForm === null) {
                die('nncncd');
                //TODO delete under code
                $options['fields'] = $responseParameters->get('fields');
                $options['entity_class'] = $this->getEntityFqcn();
                $options['entity_name'] = $responseParameters->get('entity')->getName();
                $this->filtersForm = $this->createForm(FiltersFormType::class, null, $options);
            }
            $responseParameters->set('filters_form', $this->filtersForm);
        }

        return $responseParameters;
    }

    public function overrideEntitiesActions(?EntityCollection $entities): void
    {
    }

    public function overrideGlobalActions(?ActionCollection $actions): void
    {
        if ($actions) {
            $context = $this->get(AdminContextProvider::class)->getContext();
            $adminUrlGenerator = $this->get(AdminUrlGenerator::class);

            foreach ($actions as $i => $action) {
                //récriture du bouton 'retour au parent'
                if ($action->getName() == 'index_parent') {
                    $entity = $context->getEntity()->getInstance();
                    if ($entity !== null) {
                        if ($entity->getParent() !== null) {
                            $url = $adminUrlGenerator
                                    ->setController($context->getCrud()->getControllerFqcn())
                                    ->set('entityId', $entity->getParent()->getId())
                                    ->generateUrl();
                            $action->setLinkUrl($url);
                        }
                    } else {
                        unset($actions[$i]);
                    }
                }

                if ($action->getName() == 'sort') {
                    $entityId = $context->getRequest()->get('entityId');
                    if ($entityId != null) {
                        $url = $adminUrlGenerator
                                ->setController($context->getCrud()->getControllerFqcn())
                                ->setAction($action->getName())
                                ->set('entityId', $entityId)
                                ->generateUrl();
                        $action->setLinkUrl($url);
                    }
                }
            }
        }
    }

    public function configureCrud(Crud $crud): Crud
    {
        $crud = parent::configureCrud($crud);

        $this->setMaxResults($crud);

        if ($this->isInstanceOf(SortableInterface::class)) {
            $crud->setDefaultSort(['position' => 'ASC']);
        }

        return $crud;
    }

    public function setMaxResults(Crud $crud): void
    {
        $entityClass = $this->getEntityFqcn();
        $paramListMaxResults = 'listMaxResults';
        $paramSessionListMaxResults = $entityClass . '-' . $paramListMaxResults;
        $requestListMaxResults = $this->get(RequestStack::class)->getCurrentRequest()->get($paramListMaxResults);

        if ($requestListMaxResults) {
            $this->get('session')->set($paramSessionListMaxResults, $requestListMaxResults);
        }
        $maxResults = $this->get('session')->get($paramSessionListMaxResults) ? $this->get('session')->get(
                $paramSessionListMaxResults
        ) : 30;

        $crud->setPaginatorPageSize($maxResults);
    }

    public function getSeoPanel(): ?array
    {
        if ($this->isInstanceOf(SeoInterface::class)) {
            return [
                    FormField::addPanel('seo')->setTemplateName('crud/field/generic'),
                    TextField::new('metaTitle')->setLabel('Meta Title')->setHelp(
                            'Affiché dans les résultats de recherche Google'
                    )->hideOnIndex(),
                    TextareaField::new('metaDescription')->setLabel('Meta description')->setHelp(
                            'Affiché dans les résultats de recherche Google'
                    )->hideOnIndex(),
                    CollectionField::new('oldUrls')
                            ->setFormTypeOption('entry_type', TextType::class)->setLabel(
                                    'Anciennes urls du document'
                            )->hideOnIndex(),
            ];
        } else {
            return null;
        }
    }

    public function getConfPanel(): ?array
    {
        if ($this->isInstanceOf(DevAliasInterface::class)) {
            return [
                    FormField::addPanel('configuration')->setTemplateName('crud/field/generic'),
                    TextField::new('devAlias')->hideOnIndex(),
            ];
        } else {
            return null;
        }
    }

    public function sort(AdminContext $context)
    {
        $event = new BeforeCrudActionEvent($context);
        $this->get('event_dispatcher')->dispatch($event);
        if ($event->isPropagationStopped()) {
            return $event->getResponse();
        }

        //if (!$this->isGranted(Permission::EA_EXECUTE_ACTION) || !$this->isInstanceOf(SortableInterface::class)) {
        if (!$this->isInstanceOf(SortableInterface::class)) {
            throw new ForbiddenActionException($context);
        }

        $fields = FieldCollection::new($this->configureFields(Crud::PAGE_INDEX));
        $filters = $this->get(FilterFactory::class)->create(
                $context->getCrud()->getFiltersConfig(),
                $fields,
                $context->getEntity()
        );
        $queryBuilder = $this->createIndexQueryBuilder($context->getSearch(), $context->getEntity(), $fields, $filters);
        $paginator = $this->get(PaginatorFactory::class)->create($queryBuilder);

        $entities = $this->get(EntityFactory::class)->createCollection($context->getEntity(), $paginator->getResults());
        $this->get(EntityFactory::class)->processFieldsForAll($entities, $fields);

        $sortableForm = $this->createFormBuilder(array('entities', $paginator->getResults()))
                ->add(
                        'entities',
                        CollectionType::class,
                        array(
                                'required' => true,
                                'allow_add' => true,
                                'entry_type' => PositionType::class,
                        )
                )
                ->getForm();

        $entityManager = $this->getDoctrine()->getManagerForClass($this->getEntityFqcn());
        $repository = $entityManager->getRepository($this->getEntityFqcn());

        $sortableForm->handleRequest($context->getRequest());

        if ($sortableForm->isSubmitted() && $sortableForm->isValid()) {
            foreach ($sortableForm->get('entities')->getData() as $elm) {
                $entityInstance = $repository->find($elm['id']);
                $entityDto = $context->getEntity()->newWithInstance($entityInstance);

                if (!$entityDto->isAccessible()) {
                    throw new InsufficientEntityPermissionException($context);
                }

                $event = new BeforeEntityDeletedEvent($entityInstance);
                $this->get('event_dispatcher')->dispatch($event);
                $entityInstance = $event->getEntityInstance();

                $entityInstance->setPosition($elm['position']);
                $this->updateEntity($entityManager, $entityInstance);

                $this->get('event_dispatcher')->dispatch(new AfterEntityUpdatedEvent($entityInstance));
            }

            $url = $this->get(AdminUrlGenerator::class)
                    ->setAction(Action::INDEX)
                    ->generateUrl();
            $this->addFlash('success', $this->get(TranslatorAdmin::class)->transFlashMessage('sort'), array());

            return $this->redirect($url);
        }

        $responseParameters = $this->configureResponseParameters(
                KeyValueStore::new(
                        [
                                'pageName' => Crud::PAGE_INDEX,
                                'templatePath' => '@LcSov/adminlte/crud/sort.html.twig',
                                'entities' => $entities,
                                'paginator' => $paginator,
                                'global_actions' => array(),
                                'batch_actions' => array(),
                                'filters' => $filters,
                                'sortable_form' => $sortableForm,
                        ]
                )
        );
        $responseParameters->set('fields', $this->configureFields('index'));
        $event = new AfterCrudActionEvent($context, $responseParameters);
        $this->get('event_dispatcher')->dispatch($event);
        if ($event->isPropagationStopped()) {
            return $event->getResponse();
        }

        return $responseParameters;
    }

    public function duplicate(
            AdminContext $context,
            EntityComponent $entityComponent,
            TranslatorAdmin $translatorAdmin,
            EntityManagerInterface $em
    ) {
        if (!$this->isGranted(
                Permission::EA_EXECUTE_ACTION,
                ['action' => "duplicate", 'entity' => $context->getEntity()]
        )) {
            throw new ForbiddenActionException($context);
        }

        if (!$context->getEntity()->isAccessible()) {
            throw new InsufficientEntityPermissionException($context);
        }

        $newEntity = $entityComponent->duplicateEntity($context->getEntity()->getInstance());
        $em->create($newEntity);
        $em->flush();

        $url = $this->get(AdminUrlGenerator::class)
                ->setAction(Action::EDIT)
                ->setEntityId($newEntity->getId())
                ->generateUrl();

        $this->addFlash('success', $translatorAdmin->transFlashMessage('duplicate'), array());

        return $this->redirect($url);
    }


    public function createIndexQueryBuilder(
            SearchDto $searchDto,
            EntityDto $entityDto,
            FieldCollection $fields,
            FilterCollection $filters
    ): QueryBuilder {
        $queryBuilder = parent::createIndexQueryBuilder(
                $searchDto,
                $entityDto,
                $fields,
                $filters
        );

        //TOdo utiliser les repositoryQuery ?
        if ($this->isInstanceOf(TreeInterface::class)) {
            $entityId = $searchDto->getRequest()->get('entityId');
            if ($entityId !== null) {
                $queryBuilder->andWhereParent('entity', $entityId);
            } else {
                $queryBuilder->andWhereParentIsNull('entity');
            }
        }

        $this->filtersForm = $this->createForm(
                FiltersFormType::class,
                null,
                array(
                        'fields' => $fields,
                        'entity_dto' => $entityDto,
                        'entity_class' => $this->getEntityFqcn(),
                        'entity_name' => $entityDto->getName(),
                )
        );

        $filterManager = $this->get(FilterManager::class);

        $this->filtersForm->handleRequest($searchDto->getRequest());
        /*if (($this->filtersForm->isSubmitted() && $this->filtersForm->isValid())) {

        }*/
        $filterManager->handleFiltersForm($queryBuilder, $this->filtersForm, $fields, $entityDto);


        return $queryBuilder;
    }

    public function createSortQueryBuilder(
            SearchDto $searchDto,
            EntityDto $entityDto,
            FieldCollection $fields,
            FilterCollection $filters
    ): QueryBuilder {
        $queryBuilder = $this->createIndexQueryBuilder($searchDto, $entityDto, $fields, $filters);

        return $queryBuilder;
    }

    public function edit(AdminContext $context)
    {
        $response = parent::edit($context);;

        // on vide le flash bag si édition en ajax (notification déjà affichée en Javascript)
        if ($context->getRequest()->isXmlHttpRequest()) {
            $this->get('session')->getFlashBag()->clear();
        }

        return $response;
    }

    public function isInstanceOf(string $interfaceName): bool
    {
        return in_array($interfaceName, class_implements($this->getEntityFqcn()));
    }

    public function getControllerFqcnByInterface(string $interface): string
    {
        $context = $this->get(AdminContextProvider::class)->getContext();

        return $context->getCrudControllers()->findCrudFqcnByEntityFqcn(
                $this->get(EntityManagerInterface::class)->getEntityName($interface)
        );
    }

    public function updateEntity(EntityManagerInterface $entityManager, $entityInstance): void
    {
        $entityManager->update($entityInstance);
        $entityManager->flush();
    }

    public function persistEntity(EntityManagerInterface $entityManager, $entityInstance): void
    {
        $entityManager->create($entityInstance);
        $entityManager->flush();
    }


    public function configureActions(Actions $actions): Actions
    {
        $this->buildIndexActions($actions);
        $this->buildEditActions($actions);
        $this->buildDetailActions($actions);
        $this->buildNewActions($actions);
        $this->handleTranslatableEntityActions($actions);
        $this->handleSortableEntityActions($actions);
        $this->handleTreeEntityActions($actions);

        /*$actions->reorder(Crud::PAGE_EDIT, [Action::INDEX, Action::SAVE_AND_RETURN, Action::SAVE_AND_CONTINUE, Action::DELETE]);
        $actions->reorder(Crud::PAGE_NEW, [Action::INDEX, Action::SAVE_AND_RETURN, Action::SAVE_AND_ADD_ANOTHER]);*/

        return $actions;
    }

    public function getDuplicateAction(): Action
    {
        $duplicateAction = Action::new(
                'duplicate',
                $this->get(TranslatorAdmin::class)->transAction('duplicate'),
                'fa fa-fw fa-copy'
        )
                ->linkToCrudAction('duplicate')
                ->setLabel($this->get(TranslatorAdmin::class)->transAction('duplicate'))
                ->setCssClass('in-dropdown text-info action-confirm');

        return $duplicateAction;
    }

    public function buildIndexActions(Actions $actions): void
    {
        $actions->add(Crud::PAGE_INDEX, $this->getDuplicateAction());

        $this->actionUpdate(
                $actions,
                Crud::PAGE_INDEX,
                Action::NEW,
                [
                        'icon' => 'plus',
                        'label' => $this->get(TranslatorAdmin::class)->transAction('create'),
                        'add_class' => 'btn-sm',
                ]
        );

        $this->actionUpdate(
                $actions,
                Crud::PAGE_INDEX,
                Action::EDIT,
                [
                        'class' => 'btn btn-sm btn-primary',
                        'icon' => 'edit',
                        'label' => false,
                        'html_attributes' => array(
                                'data-toggle' => 'tooltip',
                                'title' => $this->get(TranslatorAdmin::class)->transAction('edit'),
                        ),
                ]
        );

        $this->actionUpdate(
                $actions,
                Crud::PAGE_INDEX,
                Action::DETAIL,
                [
                        'icon' => 'eye',
                        'add_class' => 'btn btn-sm btn-success',
                        'label' => false,
                        'html_attributes' => array(
                                'data-toggle' => 'tooltip',
                                'title' => $this->get(TranslatorAdmin::class)->transAction('detail'),
                        ),
                ]
        );

        $this->actionUpdate(
                $actions,
                Crud::PAGE_INDEX,
                Action::DELETE,
                [
                        'icon' => 'trash',
                        'dropdown' => true,
                        'label' => $this->get(TranslatorAdmin::class)->transAction('delete'),
                ]
        );

        $this->actionUpdate(
                $actions,
                Crud::PAGE_INDEX,
                Action::BATCH_DELETE,
                [
                        'class' => 'btn btn-sm btn-danger',
                        'icon' => 'trash',
                        'label' => $this->get(TranslatorAdmin::class)->transAction('delete'),
                ]
        );
    }


    public function buildEditActions(Actions $actions): void
    {
        $actions->add(Crud::PAGE_EDIT, Action::INDEX);
        $actions->add(Crud::PAGE_EDIT, Action::DELETE);


        $this->actionUpdate(
                $actions,
                Crud::PAGE_EDIT,
                Action::SAVE_AND_RETURN,
                [
                        'add_class' => 'float-right ',
                        'icon' => 'check',
                        'label' => $this->get(TranslatorAdmin::class)->transAction('save_and_return'),
                ]
        );

        $this->actionUpdate(
                $actions,
                Crud::PAGE_EDIT,
                Action::INDEX,
                [
                        'icon' => 'chevron-left',
                        'class' => 'btn btn-link',
                        'label' => $this->get(TranslatorAdmin::class)->transAction('back_index'),
                ]
        );


        $this->actionUpdate(
                $actions,
                Crud::PAGE_EDIT,
                Action::SAVE_AND_CONTINUE,
                [
                        'class' => 'btn btn-info float-right action-save-continue',
                        'label' => $this->get(TranslatorAdmin::class)->transAction('save_and_continue'),
                ]
        );

        $this->actionUpdate(
                $actions,
                Crud::PAGE_EDIT,
                Action::DELETE,
                [
                        'icon' => 'trash',
                        'class' => 'btn btn-outline-danger action-delete',
                        'label' => $this->get(TranslatorAdmin::class)->transAction('delete'),
                ]
        );
    }

    public function buildDetailActions(Actions $actions): void
    {
    }

    public function buildNewActions(Actions $actions): void
    {
        $actions->add(Crud::PAGE_NEW, Action::INDEX);

        $this->actionUpdate(
                $actions,
                Crud::PAGE_EDIT,
                Action::SAVE_AND_RETURN,
                [
                        'add_class' => 'float-right',
                        'icon' => 'check',
                        'label' => $this->get(TranslatorAdmin::class)->transAction('save_and_return'),
                ]
        );

        $this->actionUpdate(
                $actions,
                Crud::PAGE_EDIT,
                Action::INDEX,
                [
                        'icon' => 'chevron-left',
                        'class' => 'btn btn-link',
                        'label' => $this->get(TranslatorAdmin::class)->transAction('back_index'),
                ]
        );

        $this->actionUpdate(
                $actions,
                Crud::PAGE_EDIT,
                Action::SAVE_AND_ADD_ANOTHER,
                [
                        'class' => 'btn btn-info float-right',
                        'label' => $this->get(TranslatorAdmin::class)->transAction('save_and_add_another'),
                ]
        );
    }

    public function handleTranslatableEntityActions(Actions $actions): void
    {
        if ($this->isInstanceOf(TranslatableInterface::class)) {
            $actions->update(
                    Crud::PAGE_INDEX,
                    Action::EDIT,
                    function (Action $action) {
                        $action->setTemplatePath('@LcSov/adminlte/crud/action/translatable.html.twig');

                        return $action;
                    }
            );
        }
    }

    public function handleSortableEntityActions(Actions $actions): void
    {
        if ($this->isInstanceOf(SortableInterface::class)) {
            $sortAction = Action::new('sort', $this->get(TranslatorAdmin::class)->transAction('sort'), 'fa fa-sort')
                    ->linkToCrudAction('sort')
                    ->setCssClass('btn btn-sm btn-success')
                    ->createAsGlobalAction();

            $actions->add(Crud::PAGE_INDEX, $sortAction);
        }
    }


    public function handleTreeEntityActions(Actions $actions): void
    {
        if ($this->isInstanceOf(TreeInterface::class)) {
            $indexChildAction = Action::new(
                    'index_children',
                    $this->get(TranslatorAdmin::class)->transAction('index_children'),
                    'fa fa-list'
            )
                    ->linkToCrudAction(Action::INDEX)
                    ->setLabel('')
                    ->setHtmlAttributes(array('data-toggle' => 'tooltip', 'title' => 'Afficher les enfants'))
                    ->setTemplatePath('@LcSov/adminlte/crud/action/index_children.html.twig')
                    ->setCssClass('btn btn-sm btn-success');

            $backParentAction = Action::new(
                    'index_parent',
                    $this->get(TranslatorAdmin::class)->transAction('index_parent'),
                    'fa fa-chevron-left'
            )
                    ->linkToCrudAction(Action::INDEX)
                    ->setCssClass('btn btn-sm btn-info')
                    ->createAsGlobalAction();

            $actions->add(Crud::PAGE_INDEX, $backParentAction);
            $actions->add(Crud::PAGE_INDEX, $indexChildAction);
        }
    }

    public function actionUpdate($actions, $crudActionName, $actionName, array $button): void
    {
        if ($actions->getAsDto('actions')->getAction($crudActionName, $actionName)) {
            $actions->update(
                    $crudActionName,
                    $actionName,
                    function (Action $action) use ($button) {
                        if (isset($button['add_class'])) {
                            $action->addCssClass($button['add_class']);
                        }

                        if (isset($button['class'])) {
                            $action->setCssClass($button['class']);
                        }

                        if (isset($button['icon'])) {
                            $action->setIcon('fa fa-' . $button['icon']);
                        }

                        if (isset($button['label'])) {
                            $action->setLabel($button['label']);
                        }

                        if (isset($button['dropdown']) && $button['dropdown']) {
                            $action->addCssClass('in-dropdown');
                        }

                        if (isset($button['html_attributes']) && $button['html_attributes']) {
                            $action->setHtmlAttributes($button['html_attributes']);
                        }

                        return $action;
                    }
            );
        }
    }

    public function autocompleteFilter(AdminContext $context): JsonResponse
    {
        $queryBuilder = $this->createIndexQueryBuilder(
                $context->getSearch(),
                $context->getEntity(),
                FieldCollection::new([]),
                FilterCollection::new()
        );
        $autocompleteContext = $context->getRequest()->get(AssociationField::PARAM_AUTOCOMPLETE_CONTEXT);

        /** @var CrudControllerInterface $controller */
        $controller = $this->get(ControllerFactory::class)->getCrudControllerInstance(
                $autocompleteContext[EA::CRUD_CONTROLLER_FQCN],
                Action::INDEX,
                $context->getRequest()
        );
        /** @var FieldDto $field */
        $field = FieldCollection::new(
                $controller->configureFields($autocompleteContext['originatingPage'])
        )->getByProperty($autocompleteContext['propertyName']);

        $filterManager = $this->get(FilterManager::class);

        $filterManager->applyFilter($queryBuilder, $field, $context->getRequest()->query->get('q'));
        if ($filterManager->isRelationField($field->getProperty())) {
            $queryBuilder->select($autocompleteContext['propertyName']);
        } else {
            $queryBuilder->select('entity.' . $autocompleteContext['propertyName']);
        }

        $responses = array();
        foreach ($queryBuilder->getQuery()->getArrayResult() as $result) {
            $responses[] = array_values($result)[0];
        }


        return JsonResponse::fromJsonString(json_encode($responses));
    }

    public function createCustomForm($class, $action, $controller, $entity, $dataInOption = true, $options = array())
    {
        if ($dataInOption) {
            $options['data'] = $entity;
        }

        $options['action'] = $this->get(AdminUrlGenerator::class)
                ->setAction($action)
                ->setController($controller)
                ->setEntityId($entity->getId())
                ->generateUrl();

        return $this->createForm($class, null, $options);
    }

}

