<?php

namespace Lc\SovBundle\Definition\Field;

use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField;
use EasyCorp\Bundle\EasyAdminBundle\Field\FormField;
use EasyCorp\Bundle\EasyAdminBundle\Field\IntegerField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextareaField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use Lc\SovBundle\Field\AssociationField;
use Lc\SovBundle\Field\CKEditorField;
use Lc\SovBundle\Field\CollectionField;
use Lc\SovBundle\Field\ImageManagerField;
use Lc\SovBundle\Field\StatusField;
use Lc\SovBundle\Translation\TranslatorAdmin;
use Symfony\Component\Form\Extension\Core\Type\TextType;

abstract class AbstractFieldDefinition
{
    protected TranslatorAdmin $translatorAdmin;

    public function __construct(TranslatorAdmin $translatorAdmin)
    {
        $this->translatorAdmin = $translatorAdmin;
    }

    abstract public function configureFields(): array;

    public function configureFieldsBase(): array
    {
        return [
                'id' => IntegerField::new('id')->onlyOnIndex()->setSortable(true),
                'title' => TextField::new('title'),
                'description' => CKEditorField::new('description'),
                'image' => ImageManagerField::new('image'),
                'metaTitle' => TextField::new('metaTitle')
                        ->setLabel('Meta : title')
                        ->setHelp('Affiché dans les résultats de recherche Google'),
                'metaDescription' => TextareaField::new('metaDescription')
                        ->setLabel('Meta : description')
                        ->setHelp('Affiché dans les résultats de recherche Google'),
                'oldUrls' => CollectionField::new('oldUrls')
                        ->setFormTypeOption('entry_type', TextType::class)
                        ->setLabel('Anciennes urls du document')
                        ->hideOnIndex(),
                'openGraphTitle' => TextField::new('openGraphTitle')
                        ->setLabel('OpenGraph : titre')
                        ->setHelp('Utilisé par les réseaux sociaux pour récupérer le titre de la page'),
                'openGraphDescription' => TextareaField::new('openGraphDescription')
                        ->setLabel('OpenGraph : description')
                        ->setHelp('Utilisé par les réseaux sociaux pour récupérer la description de la page'),
                'openGraphImage' => ImageManagerField::new('openGraphImage')
                        ->setLabel('OpenGraph : image'),
                'devAlias' => TextField::new('devAlias')->hideOnIndex(),
                'status' => StatusField::new('status')->setSortable(true),
                'createdAt' => DateTimeField::new('createdAt')->setSortable(true),
                'updatedAt' => DateTimeField::new('updatedAt')->setSortable(true),
                'createdBy' => AssociationField::new('createdBy'),
                'updatedBy' => AssociationField::new('updatedBy')
        ];
    }

    public function configureDefaultFields(): array
    {
        return array_keys($this->configureFields());
    }

    public function configureIndex(): array
    {
        return $this->configureDefaultFields();
    }

    public function configureDetail(): array
    {
        return $this->configureDefaultFields();
    }

    public function configureForm(): array
    {
        return $this->configureDefaultFields();
    }

    public function configurePanels(): array
    {
        return [];
    }

    public function configurePanelSeo(): array
    {
        return [
                'metaTitle',
                'metaDescription',
                'oldUrls'
        ];
    }

    public function configurePanelOpengraph(): array
    {
        return [
                'openGraphTitle',
                'openGraphDescription',
                'openGraphImage'
        ];
    }

    public function configurePanelConf(): array
    {
        return [
                'devAlias',
        ];
    }

    public function getFields(string $pageName = ''): array
    {
        if($pageName == Crud::PAGE_INDEX) {
            return $this->buildFieldArray($this->configureIndex());
        }
        elseif($pageName == Crud::PAGE_DETAIL) {
            return $this->buildFieldArray($this->configureDetail());
        }
        elseif($pageName == Crud::PAGE_EDIT || $pageName == Crud::PAGE_NEW) {
            return $this->buildFieldArrayForm();
        }

        return [];
    }

    public function getAllFields(string $pageName = null, $entity = null): array
    {
        return array_merge(
                $this->configureFieldsBase(),
                $this->configureFields($pageName, $entity),
        );
    }

    public function getFieldsByPanel(string $panel): array
    {
        return $this->buildFieldArrayFormByPanel($panel);
    }

    protected function buildFieldArray(array $configureFieldArray): array
    {
        $allFieldArray = $this->getAllFields();

        $fieldArray = [];
        foreach($configureFieldArray as $fieldName) {
            if(isset($allFieldArray[$fieldName])) {
                $fieldArray[$fieldName] = $allFieldArray[$fieldName];
            }
            else {
                throw new \ErrorException('Le field "'.$fieldName.'" n\'est pas défini dans configureFields()');
            }
        }

        return $fieldArray;
    }

    protected function buildFieldArrayForm(): array
    {
        $fieldArray = [];
        $panelArray = $this->configurePanels();

        if($panelArray && count($panelArray) > 0) {
            foreach($panelArray as $panel) {
                $fieldArray = array_merge(
                        $fieldArray,
                        $this->buildFieldArrayFormByPanel($panel)
                );
            }
        }
        else {
            $fieldArray = $this->buildFieldArray($this->configureForm());
        }

        return $fieldArray;
    }

    protected function buildFieldArrayFormByPanel(string $panel): array
    {
        $method = 'configurePanel' . ucfirst($panel);
        if(method_exists($this, $method)) {
            $panelFieldArray = $this->$method();
        }
        else{
            throw new \Exception($method . ' n\'existe pas ');
        }

        $fieldPanel = FormField::addPanel($panel);
        $method = 'panel'.ucfirst($panel).'CustomOptions';
        if(method_exists($this, $method)) {
            foreach ($this->$method() as $customOptionKey => $customOptionValue){
                $fieldPanel->setCustomOption($customOptionKey, $customOptionValue);
            }

        }

        return array_merge(
                [
                        'panel_' . $panel => $fieldPanel

                ],
                $this->buildFieldArray($panelFieldArray)
        );
    }

}
