<?php

/*
 * @author TRYDEA - 2024
 */

namespace Webapp\FileManagement\Service\XmlUtils\Normalizer\Webapp;

use Doctrine\Common\Collections\Collection;
use Webapp\Core\Entity\Individual;
use Webapp\Core\Entity\Note;
use Webapp\Core\Entity\OutExperimentationZone;
use Webapp\Core\Entity\Treatment;
use Webapp\Core\Entity\UnitPlot;
use Webapp\FileManagement\Dto\Common\ReferenceDto;
use Webapp\FileManagement\Service\XmlUtils\Normalizer\AbstractXmlNormalizer;
use Webapp\FileManagement\Service\XmlUtils\Normalizer\XmlImportConfig;

/**
 * @template-extends AbstractXmlNormalizer<UnitPlot, UnitPlotXmlDto>
 *
 * @psalm-type UnitPlotXmlDto = array{
 *     "@numero": ?string,
 *     "@traitement": ?Treatment,
 *     individus: Collection<int, Individual>,
 *     notes: Collection<int, Note>,
 *     zheAvecEpaisseurs: Collection<int, OutExperimentationZone>
 * }
 */
class UnitPlotNormalizer extends AbstractXmlNormalizer
{
    protected const ATTR_NB_INDIVIDUS = '@nbIndividus';
    protected const ATTR_NUMERO = '@numero';
    protected const ATTR_TRAITEMENT = '@traitement';
    protected const TAG_INDIVIDUS = 'individus';
    protected const TAG_ZHE_AVEC_EPAISSEURS = 'zheAvecEpaisseurs';
    protected const TAG_NOTES = 'notes';

    public const XSI_TYPE_PU_INDIVIDUEL = 'adonis.modeleMetier.plateforme:PuIndividuel';

    protected function getClass(): string
    {
        return UnitPlot::class;
    }

    public function supportsDenormalization($data, string $type, ?string $format = null, array $context = []): bool
    {
        return parent::supportsDenormalization($data, $type, $format, $context)
            && ($data[self::ATTR_XSI_TYPE] ?? self::XSI_TYPE_PU_INDIVIDUEL) !== SurfacicUnitPlotNormalizer::XSI_TYPE_PU_SURFACIQUE;
    }

    protected function getImportDataConfig(array $context): array
    {
        return [
            self::ATTR_NUMERO => 'string',
            self::ATTR_TRAITEMENT => XmlImportConfig::reference(Treatment::class),
            self::TAG_INDIVIDUS => XmlImportConfig::collection(Individual::class),
            self::TAG_ZHE_AVEC_EPAISSEURS => XmlImportConfig::collection(OutExperimentationZone::class),
            self::TAG_NOTES => XmlImportConfig::collection(Note::class),
        ];
    }

    protected function generateImportedObject($data, array $context): UnitPlot
    {
        return new UnitPlot();
    }

    protected function completeImportedObject($object, $data, ?string $format, array $context): UnitPlot
    {
        $object
            ->setNumber($data[self::ATTR_NUMERO] ?? '0')
            ->setTreatment($data[self::ATTR_TRAITEMENT])
            ->setIndividuals($data[self::TAG_INDIVIDUS])
            ->setOutExperimentationZones($data[self::TAG_ZHE_AVEC_EPAISSEURS])
            ->setNotes($data[self::TAG_NOTES]);

        return $object;
    }

    protected function extractData($object, array $context): array
    {
        return [
            self::ATTR_XSI_TYPE => self::XSI_TYPE_PU_INDIVIDUEL,
            self::ATTR_NB_INDIVIDUS => $object->getIndividuals()->count(),
            self::ATTR_NUMERO => $object->getNumber(),
            self::ATTR_TRAITEMENT => new ReferenceDto($object->getTreatment()),
            self::TAG_INDIVIDUS => $object->getIndividuals(),
            self::TAG_ZHE_AVEC_EPAISSEURS => $object->getOutExperimentationZones(),
            self::TAG_NOTES => $object->getNotes(),
        ];
    }
}
