<?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\SurfacicUnitPlot;
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<SurfacicUnitPlot, SurfacicUnitPlotXmlDto>
 *
 * @psalm-type SurfacicUnitPlotXmlDto = array{
 *      "@dateApparition": ?\DateTime,
 *      "@dateDisparition": ?\DateTime,
 *      "@idRfidCodeBarre": ?string,
 *      "@mort": ?bool,
 *      "@numero": ?string,
 *      "@traitement": ?Treatment,
 *      "@x": ?int,
 *      "@y": ?int,
 *      notes: Collection<int, Note>
 * }
 */
class SurfacicUnitPlotNormalizer extends AbstractXmlNormalizer
{
    protected const ATTR_ID_RFID_CODE_BARRE = '@idRfidCodeBarre';
    protected const ATTR_X = '@x';
    protected const ATTR_Y = '@y';
    protected const ATTR_NUMERO = '@numero';
    protected const ATTR_MORT = '@mort';
    protected const ATTR_DATE_DISPARITION = '@dateDisparition';
    protected const ATTR_TRAITEMENT = '@traitement';
    protected const ATTR_DATE_APPARITION = '@dateApparition';
    protected const TAG_NOTES = 'notes';
    public const XSI_TYPE_PU_SURFACIQUE = 'adonis.modeleMetier.plateforme:PuSurfacique';

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

    public function supportsDenormalization($data, string $type, ?string $format = null, array $context = []): bool
    {
        return parent::supportsDenormalization($data, $type, $format, $context)
            || (is_a($type, UnitPlot::class, true) && ($data[self::ATTR_XSI_TYPE] ?? null) === self::XSI_TYPE_PU_SURFACIQUE);
    }

    protected function getImportDataConfig(array $context): array
    {
        return [
            self::ATTR_NUMERO => 'string',
            self::ATTR_MORT => 'bool',
            self::ATTR_DATE_DISPARITION => \DateTime::class,
            self::ATTR_DATE_APPARITION => \DateTime::class,
            self::ATTR_X => 'int',
            self::ATTR_Y => 'int',
            self::ATTR_ID_RFID_CODE_BARRE => 'string',
            self::ATTR_TRAITEMENT => XmlImportConfig::reference(Treatment::class),
            self::TAG_NOTES => XmlImportConfig::collection(Note::class),
        ];
    }

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

    protected function completeImportedObject($object, $data, ?string $format, array $context): SurfacicUnitPlot
    {
        $object
            ->setNumber($data[self::ATTR_NUMERO] ?? '0')
            ->setDead($data[self::ATTR_MORT] ?? false)
            ->setDisappeared($data[self::ATTR_DATE_DISPARITION])
            ->setAppeared($data[self::ATTR_DATE_APPARITION])
            ->setX($data[self::ATTR_X] ?? 0)
            ->setY($data[self::ATTR_Y] ?? 0)
            ->setIdentifier($data[self::ATTR_ID_RFID_CODE_BARRE])
            ->setTreatment($data[self::ATTR_TRAITEMENT])
            ->setNotes($data[self::TAG_NOTES]);

        return $object;
    }

    protected function extractData($object, array $context): array
    {
        return [
            self::ATTR_XSI_TYPE => self::XSI_TYPE_PU_SURFACIQUE,
            self::ATTR_ID_RFID_CODE_BARRE => $object->getIdentifier(),
            self::ATTR_X => $object->getX(),
            self::ATTR_Y => $object->getY(),
            self::ATTR_NUMERO => $object->getNumber(),
            self::ATTR_MORT => $object->isDead(),
            self::ATTR_DATE_DISPARITION => $object->getDisappeared(),
            self::ATTR_TRAITEMENT => new ReferenceDto($object->getTreatment()),
            self::ATTR_DATE_APPARITION => $object->getAppeared(),
            self::TAG_NOTES => $object->getNotes(),
        ];
    }
}
