<?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\PersonBundle\DependencyInjection;

use Chill\MainBundle\DependencyInjection\MissingBundleException;
use Chill\PersonBundle\Controller\AccompanyingPeriodCommentApiController;
use Chill\PersonBundle\Controller\AccompanyingPeriodResourceApiController;
use Chill\PersonBundle\Controller\AdministrativeStatusController;
use Chill\PersonBundle\Controller\EmploymentStatusController;
use Chill\PersonBundle\Controller\HouseholdCompositionTypeApiController;
use Chill\PersonBundle\Controller\RelationApiController;
use Chill\PersonBundle\Doctrine\DQL\AddressPart;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\AdministrativeStatus;
use Chill\PersonBundle\Entity\EmploymentStatus;
use Chill\PersonBundle\Form\AdministrativeStatusType;
use Chill\PersonBundle\Form\EmploymentStatusType;
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodCommentVoter;
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodResourceVoter;
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
use Symfony\Component\DependencyInjection\Loader;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;

/**
 * Class ChillPersonExtension
 * Loads and manages your bundle configuration.
 *
 * To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html}
 */
class ChillPersonExtension extends Extension implements PrependExtensionInterface
{
    /**
     * @throws \Exception
     */
    public function load(array $configs, ContainerBuilder $container)
    {
        $configuration = new Configuration();
        $config = $this->processConfiguration($configuration, $configs);

        // set configuration for validation
        $container->setParameter(
            'chill_person.validation.birtdate_not_before',
            $config['validation']['birthdate_not_after']
        );

        $this->handlePersonFieldsParameters($container, $config['person_fields']);
        $this->handleAccompanyingPeriodsFieldsParameters($container, $config['accompanying_periods_fields']);
        $this->handleHouseholdFieldsParameters($container, $config['household_fields']);

        $container->setParameter(
            'chill_person.allow_multiple_simultaneous_accompanying_periods',
            $config['allow_multiple_simultaneous_accompanying_periods']
        );

        $container->setParameter(
            'chill_person.create_person_allowed',
            $config['create_person_allowed']
        );

        $container->setParameter(
            'chill_person.create_parcours_allowed',
            $config['create_parcours_allowed']
        );

        // register all configuration in a unique parameter
        $container->setParameter('chill_person', $config);

        $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../config'));
        $loader->load('services.yaml');
        $loader->load('services/widgets.yaml');
        $loader->load('services/fixtures.yaml');
        $loader->load('services/controller.yaml');
        $loader->load('services/search.yaml');
        $loader->load('services/menu.yaml');
        $loader->load('services/privacyEvent.yaml');
        $loader->load('services/actions.yaml');
        $loader->load('services/form.yaml');
        $loader->load('services/alt_names.yaml');
        $loader->load('services/household.yaml');
        $loader->load('services/notification.yaml');
        $loader->load('services/accompanyingPeriod.yaml');
        // We can get rid of this file when the service 'chill.person.repository.person' is no more used.
        // We should use the PersonRepository service instead of a custom service name.
        $loader->load('services/repository.yaml');
        $loader->load('services/security.yaml');
        $loader->load('services/doctrineEventListener.yaml');
        $loader->load('services/accompanyingPeriodConsistency.yaml');

        $loader->load('services/exports_person.yaml');

        if ('hidden' !== $container->getParameter('chill_person.accompanying_period')) {
            $loader->load('services/exports_accompanying_course.yaml');
            $loader->load('services/exports_social_actions.yaml');
            $loader->load('services/exports_evaluation.yaml');
            $loader->load('services/exports_accompanying_period_step_history.yaml');
        }

        $loader->load('services/exports_household.yaml');
    }

    /**
     * @throws MissingBundleException
     */
    public function prepend(ContainerBuilder $container)
    {
        $this->prependRoleHierarchy($container);
        $this->prependHomepageWidget($container);
        $this->prependDoctrineDQL($container);
        $this->prependCruds($container);
        $this->prependWorkflows($container);

        // add person_fields parameter as global
        $chillPersonConfig = $container->getExtensionConfig($this->getAlias());
        $config = $this->processConfiguration(new Configuration(), $chillPersonConfig);
        $twigConfig = [
            'globals' => [
                'chill_person' => [
                    'fields' => $config['person_fields'],
                ],
                'chill_accompanying_periods' => [
                    'fields' => $config['accompanying_periods_fields'],
                ],
                'chill_household' => [
                    'fields' => $config['household_fields'],
                ],
            ],
            'form_themes' => ['@ChillPerson/Export/ListPersonFormFields.html.twig'],
        ];
        $container->prependExtensionConfig('twig', $twigConfig);

        $this->declarePersonAsCustomizable($container);

        // declare routes for person bundle
        $container->prependExtensionConfig('chill_main', [
            'routing' => [
                'resources' => [
                    '@ChillPersonBundle/config/routes.yaml',
                ],
            ],
        ]);
    }

    protected function prependCruds(ContainerBuilder $container)
    {
        $container->prependExtensionConfig('chill_main', [
            'cruds' => [
                [
                    'class' => AccompanyingPeriod\ClosingMotive::class,
                    'name' => 'closing_motive',
                    'base_path' => '/admin/person/closing-motive',
                    'form_class' => \Chill\PersonBundle\Form\ClosingMotiveType::class,
                    'controller' => \Chill\PersonBundle\Controller\ClosingMotiveController::class,
                    'actions' => [
                        'index' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/ClosingMotive/index.html.twig',
                        ],
                        'new' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/ClosingMotive/new.html.twig',
                        ],
                        'edit' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/ClosingMotive/edit.html.twig',
                        ],
                    ],
                ],
                [
                    'class' => AccompanyingPeriod\Origin::class,
                    'name' => 'origin',
                    'base_path' => '/admin/person/origin',
                    'form_class' => \Chill\PersonBundle\Form\OriginType::class,
                    'controller' => \Chill\PersonBundle\Controller\OriginController::class,
                    'actions' => [
                        'index' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/Origin/index.html.twig',
                        ],
                        'new' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/Origin/new.html.twig',
                        ],
                        'edit' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/Origin/edit.html.twig',
                        ],
                    ],
                ],
                [
                    'class' => AdministrativeStatus::class,
                    'name' => 'administrative_status',
                    'base_path' => '/admin/administrative',
                    'base_role' => 'ROLE_ADMIN',
                    'form_class' => AdministrativeStatusType::class,
                    'controller' => AdministrativeStatusController::class,
                    'actions' => [
                        'index' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/AdministrativeStatus/index.html.twig',
                        ],
                        'new' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/AdministrativeStatus/new.html.twig',
                        ],
                        'edit' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/AdministrativeStatus/edit.html.twig',
                        ],
                    ],
                ],
                [
                    'class' => EmploymentStatus::class,
                    'name' => 'employment_status',
                    'base_path' => '/admin/employment',
                    'base_role' => 'ROLE_ADMIN',
                    'form_class' => EmploymentStatusType::class,
                    'controller' => EmploymentStatusController::class,
                    'actions' => [
                        'index' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/EmploymentStatus/index.html.twig',
                        ],
                        'new' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/EmploymentStatus/new.html.twig',
                        ],
                        'edit' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/EmploymentStatus/edit.html.twig',
                        ],
                    ],
                ],
                [
                    'class' => \Chill\PersonBundle\Entity\MaritalStatus::class,
                    'name' => 'person_marital-status',
                    'base_path' => '/admin/person/marital-status',
                    'form_class' => \Chill\PersonBundle\Form\MaritalStatusType::class,
                    'controller' => \Chill\PersonBundle\Controller\MaritalStatusController::class,
                    'actions' => [
                        'index' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/MaritalStatus/index.html.twig',
                        ],
                        'new' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/MaritalStatus/new.html.twig',
                        ],
                        'edit' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/MaritalStatus/edit.html.twig',
                        ],
                    ],
                ],
                [
                    'class' => \Chill\PersonBundle\Entity\Household\Position::class,
                    'name' => 'person_household_position',
                    'base_path' => '/admin/person/household/position',
                    'form_class' => \Chill\PersonBundle\Form\HouseholdPositionType::class,
                    'controller' => \Chill\PersonBundle\Controller\HouseholdPositionController::class,
                    'actions' => [
                        'index' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/HouseholdPosition/index.html.twig',
                        ],
                        'new' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/HouseholdPosition/new.html.twig',
                        ],
                        'edit' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/HouseholdPosition/edit.html.twig',
                        ],
                    ],
                ],
                [
                    'class' => \Chill\PersonBundle\Entity\Household\HouseholdCompositionType::class,
                    'name' => 'person_household_composition_type',
                    'base_path' => '/admin/person/household/composition-type',
                    'form_class' => \Chill\PersonBundle\Form\HouseholdCompositionTypeType::class,
                    'controller' => \Chill\PersonBundle\Controller\HouseholdCompositionTypeController::class,
                    'actions' => [
                        'index' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/HouseholdCompositionType/index.html.twig',
                        ],
                        'new' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/HouseholdCompositionType/new.html.twig',
                        ],
                        'edit' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/HouseholdCompositionType/edit.html.twig',
                        ],
                    ],
                ],
                [
                    'class' => \Chill\PersonBundle\Entity\Relationships\Relation::class,
                    'name' => 'person_relation',
                    'base_path' => '/admin/person/relation',
                    'form_class' => \Chill\PersonBundle\Form\RelationType::class,
                    'controller' => \Chill\PersonBundle\Controller\RelationController::class,
                    'actions' => [
                        'index' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/Relation/index.html.twig',
                        ],
                        'new' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/Relation/new.html.twig',
                        ],
                        'edit' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/Relation/edit.html.twig',
                        ],
                    ],
                ],
                [
                    'class' => \Chill\PersonBundle\Entity\Person\PersonResourceKind::class,
                    'name' => 'person_resource-kind',
                    'base_path' => '/admin/person/resource-kind',
                    'form_class' => \Chill\PersonBundle\Form\PersonResourceKindType::class,
                    'controller' => \Chill\PersonBundle\Controller\PersonResourceKindController::class,
                    'actions' => [
                        'index' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/PersonResourceKind/index.html.twig',
                        ],
                        'new' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/PersonResourceKind/new.html.twig',
                        ],
                        'edit' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/PersonResourceKind/edit.html.twig',
                        ],
                    ],
                ],
                [
                    'class' => \Chill\PersonBundle\Entity\SocialWork\SocialIssue::class,
                    'name' => 'social_issue',
                    'base_path' => '/admin/social-work/social-issue',
                    'form_class' => \Chill\PersonBundle\Form\SocialWork\SocialIssueType::class,
                    'controller' => \Chill\PersonBundle\Controller\SocialWork\SocialIssueController::class,
                    'actions' => [
                        'index' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/SocialWork/SocialIssue/index.html.twig',
                        ],
                        'new' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/SocialWork/new.html.twig',
                        ],
                        'edit' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/SocialWork/SocialIssue/edit.html.twig',
                        ],
                    ],
                ],
                [
                    'class' => \Chill\PersonBundle\Entity\SocialWork\SocialAction::class,
                    'name' => 'social_action',
                    'base_path' => '/admin/social-work/social-action',
                    'form_class' => \Chill\PersonBundle\Form\SocialWork\SocialActionType::class,
                    'controller' => \Chill\PersonBundle\Controller\SocialWork\SocialActionController::class,
                    'actions' => [
                        'index' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/SocialWork/SocialAction/index.html.twig',
                        ],
                        'new' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/SocialWork/new.html.twig',
                        ],
                        'edit' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/SocialWork/SocialAction/edit.html.twig',
                        ],
                    ],
                ],
                [
                    'class' => \Chill\PersonBundle\Entity\SocialWork\Goal::class,
                    'name' => 'social_goal',
                    'base_path' => '/admin/social-work/goal',
                    'form_class' => \Chill\PersonBundle\Form\SocialWork\GoalType::class,
                    'controller' => \Chill\PersonBundle\Controller\SocialWork\GoalController::class,
                    'actions' => [
                        'index' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/SocialWork/Goal/index.html.twig',
                        ],
                        'new' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/SocialWork/new.html.twig',
                        ],
                        'edit' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/SocialWork/edit.html.twig',
                        ],
                    ],
                ],
                [
                    'class' => \Chill\PersonBundle\Entity\SocialWork\Result::class,
                    'name' => 'social_result',
                    'base_path' => '/admin/social-work/result',
                    'form_class' => \Chill\PersonBundle\Form\SocialWork\ResultType::class,
                    'controller' => \Chill\PersonBundle\Controller\SocialWork\ResultController::class,
                    'actions' => [
                        'index' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/SocialWork/Result/index.html.twig',
                        ],
                        'new' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/SocialWork/new.html.twig',
                        ],
                        'edit' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/SocialWork/edit.html.twig',
                        ],
                    ],
                ],
                [
                    'class' => \Chill\PersonBundle\Entity\SocialWork\Evaluation::class,
                    'name' => 'social_evaluation',
                    'base_path' => '/admin/social-work/evaluation',
                    'form_class' => \Chill\PersonBundle\Form\SocialWork\EvaluationType::class,
                    'controller' => \Chill\PersonBundle\Controller\SocialWork\EvaluationController::class,
                    'actions' => [
                        'index' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/SocialWork/Evaluation/index.html.twig',
                        ],
                        'new' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/SocialWork/new.html.twig',
                        ],
                        'edit' => [
                            'role' => 'ROLE_ADMIN',
                            'template' => '@ChillPerson/SocialWork/edit.html.twig',
                        ],
                    ],
                ],
            ],
            'apis' => [
                [
                    'class' => AccompanyingPeriod::class,
                    'name' => 'accompanying_course',
                    'base_path' => '/api/1.0/person/accompanying-course',
                    'controller' => \Chill\PersonBundle\Controller\AccompanyingCourseApiController::class,
                    'actions' => [
                        '_entity' => [
                            'roles' => [
                                Request::METHOD_GET => AccompanyingPeriodVoter::SEE,
                                Request::METHOD_PATCH => AccompanyingPeriodVoter::SEE,
                                Request::METHOD_PUT => AccompanyingPeriodVoter::SEE,
                            ],
                            'methods' => [
                                Request::METHOD_GET => true,
                                Request::METHOD_PUT => true,
                                Request::METHOD_PATCH => true,
                            ],
                        ],
                        'participation' => [
                            'methods' => [
                                Request::METHOD_POST => true,
                                Request::METHOD_DELETE => true,
                                Request::METHOD_GET => false,
                                Request::METHOD_HEAD => false,
                            ],
                            'roles' => [
                                Request::METHOD_POST => AccompanyingPeriodVoter::SEE,
                                Request::METHOD_DELETE => AccompanyingPeriodVoter::SEE,
                            ],
                        ],
                        'resource' => [
                            'methods' => [
                                Request::METHOD_POST => true,
                                Request::METHOD_DELETE => true,
                                Request::METHOD_GET => false,
                                Request::METHOD_HEAD => false,
                            ],
                            'roles' => [
                                Request::METHOD_POST => AccompanyingPeriodVoter::SEE,
                                Request::METHOD_DELETE => AccompanyingPeriodVoter::SEE,
                            ],
                        ],
                        'comment' => [
                            'methods' => [
                                Request::METHOD_POST => true,
                                Request::METHOD_DELETE => true,
                                Request::METHOD_GET => false,
                                Request::METHOD_HEAD => false,
                            ],
                            'roles' => [
                                Request::METHOD_POST => AccompanyingPeriodVoter::SEE,
                                Request::METHOD_DELETE => AccompanyingPeriodVoter::SEE,
                            ],
                        ],
                        'requestor' => [
                            'methods' => [
                                Request::METHOD_POST => true,
                                Request::METHOD_DELETE => true,
                                Request::METHOD_GET => false,
                                Request::METHOD_HEAD => false,
                            ],
                            'roles' => [
                                Request::METHOD_POST => AccompanyingPeriodVoter::SEE,
                                Request::METHOD_DELETE => AccompanyingPeriodVoter::SEE,
                            ],
                        ],
                        'scope' => [
                            'methods' => [
                                Request::METHOD_POST => true,
                                Request::METHOD_DELETE => true,
                                Request::METHOD_GET => false,
                                Request::METHOD_HEAD => false,
                            ],
                            'roles' => [
                                Request::METHOD_POST => AccompanyingPeriodVoter::SEE,
                                Request::METHOD_DELETE => AccompanyingPeriodVoter::SEE,
                            ],
                        ],
                        'socialissue' => [
                            'methods' => [
                                Request::METHOD_POST => true,
                                Request::METHOD_DELETE => true,
                                Request::METHOD_GET => false,
                                Request::METHOD_HEAD => false,
                            ],
                            'controller_action' => 'socialIssueApi',
                            'roles' => [
                                Request::METHOD_POST => AccompanyingPeriodVoter::SEE,
                                Request::METHOD_DELETE => AccompanyingPeriodVoter::SEE,
                            ],
                        ],
                        'work' => [
                            'methods' => [
                                Request::METHOD_POST => true,
                                Request::METHOD_DELETE => false,
                                Request::METHOD_GET => false,
                                Request::METHOD_HEAD => false,
                            ],
                            'controller_action' => 'workApi',
                            'roles' => [
                                Request::METHOD_POST => AccompanyingPeriodVoter::SEE,
                                Request::METHOD_DELETE => 'ALWAYS_FAILS',
                            ],
                        ],
                        'confirm' => [
                            'methods' => [
                                Request::METHOD_POST => true,
                                Request::METHOD_GET => false,
                                Request::METHOD_HEAD => false,
                            ],
                            'roles' => [
                                Request::METHOD_POST => AccompanyingPeriodVoter::SEE,
                            ],
                        ],
                        // 'confidential' => [
                        //     'methods' => [
                        //         Request::METHOD_POST => true,
                        //         Request::METHOD_GET => true,
                        //     ],
                        //     'controller_action' => 'toggleConfidentialApi',
                        //     'roles' => [
                        //         Request::METHOD_POST => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::TOGGLE_CONFIDENTIAL,
                        //     ],
                        // ],
                        'findAccompanyingPeriodsByPerson' => [
                            'path' => '/by-person/{person_id}.{_format}',
                            'controller_action' => 'getAccompanyingPeriodsByPerson',
                            'methods' => [
                                Request::METHOD_GET => true,
                                Request::METHOD_HEAD => true,
                            ],
                        ],
                    ],
                ],
                [
                    'class' => AccompanyingPeriod\Comment::class,
                    'controller' => AccompanyingPeriodCommentApiController::class,
                    'name' => 'accompanying_period_comment',
                    'base_path' => '/api/1.0/person/accompanying-period/comment',
                    'base_role' => 'ROLE_USER',
                    'actions' => [
                        '_entity' => [
                            'methods' => [
                                Request::METHOD_GET => false,
                                Request::METHOD_PATCH => true,
                                Request::METHOD_HEAD => false,
                                Request::METHOD_DELETE => false,
                            ],
                            'roles' => [
                                Request::METHOD_PATCH => AccompanyingPeriodCommentVoter::EDIT,
                            ],
                        ],
                    ],
                ],
                [
                    'class' => AccompanyingPeriod\Resource::class,
                    'controller' => AccompanyingPeriodResourceApiController::class,
                    'name' => 'accompanying_period_resource',
                    'base_path' => '/api/1.0/person/accompanying-period/resource',
                    'base_role' => 'ROLE_USER',
                    'actions' => [
                        '_entity' => [
                            'methods' => [
                                Request::METHOD_GET => false,
                                Request::METHOD_PATCH => true,
                                Request::METHOD_HEAD => false,
                                Request::METHOD_DELETE => false,
                            ],
                            'roles' => [
                                Request::METHOD_PATCH => AccompanyingPeriodResourceVoter::EDIT,
                            ],
                        ],
                    ],
                ],
                [
                    'class' => AccompanyingPeriod\Origin::class,
                    'name' => 'accompanying_period_origin',
                    'base_path' => '/api/1.0/person/accompanying-period/origin',
                    'controller' => \Chill\PersonBundle\Controller\OpeningApiController::class,
                    'base_role' => 'ROLE_USER',
                    'actions' => [
                        '_index' => [
                            'methods' => [
                                Request::METHOD_GET => true,
                                Request::METHOD_HEAD => true,
                            ],
                        ],
                        '_entity' => [
                            'methods' => [
                                Request::METHOD_GET => true,
                                Request::METHOD_HEAD => true,
                            ],
                        ],
                    ],
                ],
                [
                    'class' => \Chill\PersonBundle\Entity\SocialWork\SocialIssue::class,
                    'name' => 'social_work_social_issue',
                    'controller' => \Chill\PersonBundle\Controller\SocialIssueApiController::class,
                    'base_path' => '/api/1.0/person/social-work/social-issue',
                    'base_role' => 'ROLE_USER',
                    'actions' => [
                        '_index' => [
                            'methods' => [
                                Request::METHOD_GET => true,
                                Request::METHOD_HEAD => true,
                            ],
                        ],
                        '_entity' => [
                            'methods' => [
                                Request::METHOD_GET => true,
                                Request::METHOD_HEAD => true,
                            ],
                        ],
                    ],
                ],
                [
                    'class' => \Chill\PersonBundle\Entity\Person::class,
                    'name' => 'person',
                    'base_path' => '/api/1.0/person/person',
                    'base_role' => PersonVoter::SEE,
                    'controller' => \Chill\PersonBundle\Controller\PersonApiController::class,
                    'actions' => [
                        '_entity' => [
                            'methods' => [
                                Request::METHOD_GET => true,
                                Request::METHOD_HEAD => true,
                                Request::METHOD_POST => true,
                                Request::METHOD_PATCH => true,
                            ],
                            'roles' => [
                                Request::METHOD_GET => PersonVoter::SEE,
                                Request::METHOD_HEAD => PersonVoter::SEE,
                                Request::METHOD_POST => PersonVoter::CREATE,
                                Request::METHOD_PATCH => PersonVoter::CREATE,
                            ],
                        ],
                        'address' => [
                            'methods' => [
                                Request::METHOD_POST => true,
                                Request::METHOD_DELETE => true,
                                Request::METHOD_GET => false,
                                Request::METHOD_HEAD => false,
                            ],
                            'controller_action' => 'personAddressApi',
                        ],
                    ],
                ],
                [
                    'class' => \Chill\PersonBundle\Entity\Household\Household::class,
                    'controller' => \Chill\PersonBundle\Controller\HouseholdApiController::class,
                    'name' => 'household',
                    'base_path' => '/api/1.0/person/household',
                    'base_role' => 'ROLE_USER',
                    'actions' => [
                        '_index' => [
                            'methods' => [
                                Request::METHOD_GET => true,
                                Request::METHOD_HEAD => true,
                            ],
                        ],
                        '_entity' => [
                            'methods' => [
                                Request::METHOD_GET => true,
                                Request::METHOD_HEAD => true,
                                Request::METHOD_POST => true,
                            ],
                        ],
                        'suggestHouseholdByAccompanyingPeriodParticipation' => [
                            'path' => '/suggest/by-person/{person_id}/through-accompanying-period-participation.{_format}',
                            'methods' => [
                                Request::METHOD_GET => true,
                                Request::METHOD_HEAD => true,
                            ],
                        ],
                    ],
                ],
                [
                    'class' => \Chill\PersonBundle\Entity\SocialWork\SocialAction::class,
                    'name' => 'social_action',
                    'base_path' => '/api/1.0/person/social/social-action',
                    'controller' => \Chill\PersonBundle\Controller\SocialWorkSocialActionApiController::class,
                    // TODO: acl
                    'base_role' => 'ROLE_USER',
                    'actions' => [
                        '_entity' => [
                            'methods' => [
                                Request::METHOD_GET => true,
                                Request::METHOD_HEAD => true,
                            ],
                            'roles' => [
                                Request::METHOD_GET => 'ROLE_USER',
                                Request::METHOD_HEAD => 'ROLE_USER',
                            ],
                        ],
                        '_index' => [
                            'methods' => [
                                Request::METHOD_GET => true,
                                Request::METHOD_HEAD => true,
                            ],
                            'roles' => [
                                Request::METHOD_GET => 'ROLE_USER',
                                Request::METHOD_HEAD => 'ROLE_USER',
                            ],
                        ],
                        'listBySocialIssue' => [
                            'single-collection' => 'collection',
                            'path' => '/by-social-issue/{id}.{_format}',
                            'methods' => [
                                Request::METHOD_GET => true,
                                Request::METHOD_HEAD => true,
                            ],
                            'roles' => [
                                Request::METHOD_GET => 'ROLE_USER',
                                Request::METHOD_HEAD => 'ROLE_USER',
                            ],
                        ],
                    ],
                ],
                [
                    'class' => AccompanyingPeriod\AccompanyingPeriodWork::class,
                    'name' => 'accompanying_period_work',
                    'base_path' => '/api/1.0/person/accompanying-course/work',
                    'controller' => \Chill\PersonBundle\Controller\AccompanyingCourseWorkApiController::class,
                    // TODO: acl
                    'base_role' => 'ROLE_USER',
                    'actions' => [
                        '_entity' => [
                            'methods' => [
                                Request::METHOD_GET => true,
                                Request::METHOD_HEAD => true,
                                Request::METHOD_PATCH => true,
                                Request::METHOD_PUT => true,
                            ],
                            'roles' => [
                                Request::METHOD_GET => 'ROLE_USER',
                                Request::METHOD_HEAD => 'ROLE_USER',
                                Request::METHOD_PATCH => 'ROLE_USER',
                                Request::METHOD_PUT => 'ROLE_USER',
                            ],
                        ],
                    ],
                ],
                [
                    'class' => \Chill\PersonBundle\Entity\SocialWork\Result::class,
                    'controller' => \Chill\PersonBundle\Controller\SocialWorkResultApiController::class,
                    'name' => 'social_work_result',
                    'base_path' => '/api/1.0/person/social-work/result',
                    'base_role' => 'ROLE_USER',
                    'actions' => [
                        '_entity' => [
                            'methods' => [
                                Request::METHOD_GET => true,
                                Request::METHOD_HEAD => true,
                            ],
                            'roles' => [
                                Request::METHOD_GET => 'ROLE_USER',
                                Request::METHOD_HEAD => 'ROLE_USER',
                            ],
                        ],
                        '_index' => [
                            'methods' => [
                                Request::METHOD_GET => true,
                                Request::METHOD_HEAD => true,
                            ],
                            'roles' => [
                                Request::METHOD_GET => 'ROLE_USER',
                                Request::METHOD_HEAD => 'ROLE_USER',
                            ],
                        ],
                        'by-social-action' => [
                            'single-collection' => 'collection',
                            'path' => '/by-social-action/{id}.{_format}',
                            'controller_action' => 'listBySocialAction',
                            'methods' => [
                                Request::METHOD_GET => true,
                                Request::METHOD_HEAD => true,
                            ],
                            'roles' => [
                                Request::METHOD_GET => 'ROLE_USER',
                                Request::METHOD_HEAD => 'ROLE_USER',
                            ],
                        ],
                        'by-goal' => [
                            'single-collection' => 'collection',
                            'path' => '/by-goal/{id}.{_format}',
                            'controller_action' => 'listByGoal',
                            'methods' => [
                                Request::METHOD_GET => true,
                                Request::METHOD_HEAD => true,
                            ],
                            'roles' => [
                                Request::METHOD_GET => 'ROLE_USER',
                                Request::METHOD_HEAD => 'ROLE_USER',
                            ],
                        ],
                    ],
                ],
                [
                    'class' => \Chill\PersonBundle\Entity\SocialWork\Goal::class,
                    'controller' => \Chill\PersonBundle\Controller\SocialWorkGoalApiController::class,
                    'name' => 'social_work_goal',
                    'base_path' => '/api/1.0/person/social-work/goal',
                    'base_role' => 'ROLE_USER',
                    'actions' => [
                        '_entity' => [
                            'methods' => [
                                Request::METHOD_GET => true,
                                Request::METHOD_HEAD => true,
                            ],
                            'roles' => [
                                Request::METHOD_GET => 'ROLE_USER',
                                Request::METHOD_HEAD => 'ROLE_USER',
                            ],
                        ],
                        '_index' => [
                            'methods' => [
                                Request::METHOD_GET => true,
                                Request::METHOD_HEAD => true,
                            ],
                            'roles' => [
                                Request::METHOD_GET => 'ROLE_USER',
                                Request::METHOD_HEAD => 'ROLE_USER',
                            ],
                        ],
                        'by-social-action' => [
                            'single-collection' => 'collection',
                            'path' => '/by-social-action/{id}.{_format}',
                            'controller_action' => 'listBySocialAction',
                            'methods' => [
                                Request::METHOD_GET => true,
                                Request::METHOD_HEAD => true,
                            ],
                            'roles' => [
                                Request::METHOD_GET => 'ROLE_USER',
                                Request::METHOD_HEAD => 'ROLE_USER',
                            ],
                        ],
                    ],
                ],
                [
                    'class' => \Chill\PersonBundle\Entity\Relationships\Relationship::class,
                    'controller' => \Chill\PersonBundle\Controller\RelationshipApiController::class,
                    'name' => 'relationship_by_person',
                    'base_path' => '/api/1.0/relations/relationship',
                    'base_role' => 'ROLE_USER',
                    'actions' => [
                        '_entity' => [
                            'methods' => [
                                Request::METHOD_POST => true,
                                Request::METHOD_PATCH => true,
                                Request::METHOD_DELETE => true,
                            ],
                            'roles' => [
                                Request::METHOD_POST => 'ROLE_USER',
                                Request::METHOD_PATCH => 'ROLE_USER',
                                Request::METHOD_DELETE => 'ROLE_USER',
                            ],
                        ],
                        'relationship-by-person' => [
                            'path' => '/by-person/{person_id}.json',
                            'controller_action' => 'getRelationshipsByPerson',
                            'methods' => [
                                Request::METHOD_GET => true,
                                Request::METHOD_HEAD => true,
                            ],
                            'roles' => [
                                Request::METHOD_GET => 'ROLE_USER',
                                Request::METHOD_HEAD => 'ROLE_USER',
                            ],
                        ],
                    ],
                ],
                [
                    'class' => \Chill\PersonBundle\Entity\Relationships\Relation::class,
                    'controller' => RelationApiController::class,
                    'name' => 'relations',
                    'base_path' => '/api/1.0/relations/relation',
                    'base_role' => 'ROLE_USER',
                    'actions' => [
                        '_index' => [
                            'methods' => [
                                Request::METHOD_GET => true,
                                Request::METHOD_HEAD => true,
                            ],
                        ],
                        '_entity' => [
                            'methods' => [
                                Request::METHOD_GET => true,
                                Request::METHOD_HEAD => true,
                            ],
                        ],
                    ],
                ],
                [
                    'class' => \Chill\PersonBundle\Entity\Household\HouseholdCompositionType::class,
                    'name' => 'household_composition',
                    'base_path' => '/api/1.0/person/houehold/composition/type',
                    'base_role' => 'ROLE_USER',
                    'controller' => HouseholdCompositionTypeApiController::class,
                    'actions' => [
                        '_index' => [
                            'methods' => [
                                Request::METHOD_GET => true,
                                Request::METHOD_HEAD => true,
                            ],
                        ],
                    ],
                ],
            ],
        ]);
    }

    /**
     * Add DQL function linked with person.
     */
    protected function prependDoctrineDQL(ContainerBuilder $container)
    {
        // add DQL function to ORM (default entity_manager)

        $container->prependExtensionConfig('doctrine', [
            'orm' => [
                'dql' => [
                    'string_functions' => [
                        'GET_PERSON_ADDRESS_ADDRESS_ID' => AddressPart\AddressPartAddressId::class,
                        'GET_PERSON_ADDRESS_STREET_ADDRESS_1' => AddressPart\AddressPartStreetAddress1::class,
                        'GET_PERSON_ADDRESS_STREET_ADDRESS_2' => AddressPart\AddressPartStreetAddress2::class,
                        'GET_PERSON_ADDRESS_VALID_FROM' => AddressPart\AddressPartValidFrom::class,
                        'GET_PERSON_ADDRESS_POSTCODE_LABEL' => AddressPart\AddressPartPostCodeLabel::class,
                        'GET_PERSON_ADDRESS_POSTCODE_CODE' => AddressPart\AddressPartPostCodeCode::class,
                        'GET_PERSON_ADDRESS_POSTCODE_ID' => AddressPart\AddressPartPostCodeId::class,
                        'GET_PERSON_ADDRESS_COUNTRY_NAME' => AddressPart\AddressPartCountryName::class,
                        'GET_PERSON_ADDRESS_COUNTRY_CODE' => AddressPart\AddressPartCountryCode::class,
                        'GET_PERSON_ADDRESS_COUNTRY_ID' => AddressPart\AddressPartCountryId::class,
                    ],
                    'numeric_functions' => [
                        'GET_PERSON_ADDRESS_ISNOADDRESS' => AddressPart\AddressPartIsNoAddress::class,
                    ],
                ],
            ],
        ]);
    }

    /**
     * Add a widget "add a person" on the homepage, automatically.
     */
    protected function prependHomepageWidget(ContainerBuilder $container)
    {
        $container->prependExtensionConfig('chill_main', [
            'widgets' => [
                'homepage' => [
                    [
                        'widget_alias' => 'add_person',
                        'order' => 2,
                    ],
                ],
            ],
        ]);
    }

    /**
     * Add role hierarchy.
     */
    protected function prependRoleHierarchy(ContainerBuilder $container)
    {
        $container->prependExtensionConfig('security', [
            'role_hierarchy' => [
                PersonVoter::UPDATE => [PersonVoter::SEE],
                PersonVoter::CREATE => [PersonVoter::SEE],
                // accompanying period
                AccompanyingPeriodVoter::SEE_DETAILS => [AccompanyingPeriodVoter::SEE],
                AccompanyingPeriodVoter::CREATE => [AccompanyingPeriodVoter::SEE_DETAILS],
                AccompanyingPeriodVoter::DELETE => [AccompanyingPeriodVoter::SEE_DETAILS],
                AccompanyingPeriodVoter::EDIT => [AccompanyingPeriodVoter::SEE_DETAILS],
                // give all ACL for FULL
                AccompanyingPeriodVoter::FULL => [
                    AccompanyingPeriodVoter::SEE_DETAILS,
                    AccompanyingPeriodVoter::CREATE,
                    AccompanyingPeriodVoter::EDIT,
                    AccompanyingPeriodVoter::DELETE,
                ],
                AccompanyingPeriodVoter::TOGGLE_CONFIDENTIAL_ALL => [
                    AccompanyingPeriodVoter::SEE_CONFIDENTIAL_ALL,
                ],
            ],
        ]);
    }

    protected function prependWorkflows(ContainerBuilder $container)
    {
        $container->prependExtensionConfig('framework', [
            'workflows' => [
                'accompanying_period_lifecycle' => [
                    'type' => 'state_machine',
                    'audit_trail' => [
                        'enabled' => true,
                    ],
                    'marking_store' => [
                        'type' => 'method',
                        'property' => 'step',
                    ],
                    'supports' => [
                        AccompanyingPeriod::class,
                    ],
                    'initial_marking' => 'DRAFT',
                    'places' => [
                        AccompanyingPeriod::STEP_DRAFT,
                        AccompanyingPeriod::STEP_CONFIRMED,
                        AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_SHORT,
                        AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_LONG,
                        AccompanyingPeriod::STEP_CLOSED,
                    ],
                    'transitions' => [
                        'confirm' => [
                            'from' => AccompanyingPeriod::STEP_DRAFT,
                            'to' => AccompanyingPeriod::STEP_CONFIRMED,
                        ],
                        'mark_inactive_short' => [
                            'from' => AccompanyingPeriod::STEP_CONFIRMED,
                            'to' => AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_SHORT,
                        ],
                        'mark_inactive_long' => [
                            'from' => [
                                AccompanyingPeriod::STEP_CONFIRMED,
                                AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_SHORT,
                            ],
                            'to' => AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_LONG,
                        ],
                        'mark_active' => [
                            'from' => [
                                AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_LONG,
                                AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_SHORT,
                            ],
                            'to' => AccompanyingPeriod::STEP_CONFIRMED,
                        ],
                        'close' => [
                            'from' => [
                                AccompanyingPeriod::STEP_CONFIRMED,
                                AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_SHORT,
                                AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_LONG,
                            ],
                            'to' => AccompanyingPeriod::STEP_CLOSED,
                        ],
                    ],
                ],
            ],
        ]);
    }

    /**
     * @throws MissingBundleException
     */
    private function declarePersonAsCustomizable(ContainerBuilder $container)
    {
        $bundles = $container->getParameter('kernel.bundles');

        if (!isset($bundles['ChillCustomFieldsBundle'])) {
            throw new MissingBundleException('ChillCustomFieldsBundle');
        }

        $container->prependExtensionConfig(
            'chill_custom_fields',
            ['customizables_entities' => [
                ['class' => \Chill\PersonBundle\Entity\Person::class, 'name' => 'PersonEntity'],
            ],
            ]
        );
    }

    private function handleAccompanyingPeriodsFieldsParameters(ContainerBuilder $container, $config)
    {
        $container->setParameter('chill_person.accompanying_period_fields', $config);

        foreach ($config as $key => $value) {
            switch ($key) {
                case 'enabled':
                    break;

                default:
                    $container->setParameter('chill_person.accompanying_period_fields.'.$key, $value);

                    break;
            }
        }
    }

    private function handleHouseholdFieldsParameters(ContainerBuilder $container, $config)
    {
        $container->setParameter('chill_person.household_fields', $config);

        foreach ($config as $key => $value) {
            switch ($key) {
                case 'enabled':
                    break;

                default:
                    $container->setParameter('chill_person.household_fields.'.$key, $value);

                    break;
            }
        }
    }

    private function handlePersonFieldsParameters(ContainerBuilder $container, $config)
    {
        if (\array_key_exists('enabled', $config)) {
            unset($config['enabled']);
        }

        $container->setParameter('chill_person.person_fields', $config);

        foreach ($config as $key => $value) {
            match ($key) {
                'accompanying_period' => $container->setParameter('chill_person.accompanying_period', $value),
                default => $container->setParameter('chill_person.person_fields.'.$key, $value),
            };
        }
    }
}
