<?php

/*
 * @author TRYDEA - 2024
 */

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

use Doctrine\Common\Collections\Collection;
use Webapp\Core\Entity\Note;
use Webapp\Core\Entity\OutExperimentationZone;
use Webapp\Core\Entity\SubBlock;
use Webapp\Core\Entity\SurfacicUnitPlot;
use Webapp\Core\Entity\UnitPlot;
use Webapp\FileManagement\Service\XmlUtils\Normalizer\AbstractXmlNormalizer;
use Webapp\FileManagement\Service\XmlUtils\Normalizer\XmlImportConfig;

/**
 * @template-extends AbstractXmlNormalizer<SubBlock, SubBlockXmlDto>
 *
 * @psalm-type SubBlockXmlDto =array{
 *      "@numero": ?string,
 *      notes: Collection<int, Note>,
 *      parcellesUnitaire: Collection<int, UnitPlot|SurfacicUnitPlot>,
 *      zheAvecEpaisseurs: Collection<int, OutExperimentationZone>
 * }
 */
class SubBlockNormalizer extends AbstractXmlNormalizer
{
    protected const ATTR_NUMERO = '@numero';
    protected const TAG_PARCELLES_UNITAIRE = 'parcellesUnitaire';
    protected const TAG_ZHE_AVEC_EPAISSEURS = 'zheAvecEpaisseurs';
    protected const TAG_NOTES = 'notes';

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

    protected function getImportDataConfig(array $context): array
    {
        return [
            self::ATTR_NUMERO => 'string',
            self::TAG_ZHE_AVEC_EPAISSEURS => XmlImportConfig::collection(OutExperimentationZone::class),
            self::TAG_PARCELLES_UNITAIRE => XmlImportConfig::values(UnitPlot::class),
            self::TAG_NOTES => XmlImportConfig::collection(Note::class),
        ];
    }

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

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

        foreach ($data[self::TAG_PARCELLES_UNITAIRE] as $item) {
            if ($item instanceof UnitPlot) {
                $object->addUnitPlots($item);
            } else {
                $object->addSurfacicUnitPlots($item);
            }
        }

        return $object;
    }

    protected function extractData($object, array $context): array
    {
        return [
            self::ATTR_NUMERO => $object->getNumber(),
            self::TAG_PARCELLES_UNITAIRE => array_merge($object->getUnitPlots()->getValues(), $object->getSurfacicUnitPlots()->getValues()),
            self::TAG_ZHE_AVEC_EPAISSEURS => $object->getOutExperimentationZones(),
            self::TAG_NOTES => $object->getNotes(),
        ];
    }
}
