<?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\FileManagement\Service\XmlUtils\Normalizer\AbstractXmlNormalizer;
use Webapp\FileManagement\Service\XmlUtils\Normalizer\XmlImportConfig;

/**
 * @template-extends AbstractXmlNormalizer<Individual, IndividualXmlDto>
 *
 * @psalm-type IndividualXmlDto = array{
 *      "@dateApparition": ?\DateTime,
 *      "@dateDisparition": ?\DateTime,
 *      "@idRfidCodeBarre": ?string,
 *      "@mort": ?bool,
 *      "@numero": ?string,
 *      "@x": ?int,
 *      "@y": ?int,
 *      notes: Collection<int, Note>
 * }
 */
class IndividualNormalizer extends AbstractXmlNormalizer
{
    protected const TAG_NOTES = 'notes';
    protected const ATTR_ID_RFID_CODE_BARRE = '@idRfidCodeBarre';
    protected const ATTR_DATE_APPARITION = '@dateApparition';
    protected const ATTR_DATE_DISPARITION = '@dateDisparition';
    protected const ATTR_MORT = '@mort';
    protected const ATTR_NUMERO = '@numero';
    protected const ATTR_Y = '@y';
    protected const ATTR_X = '@x';

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

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

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

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

        if ($object->isDead()) {
            $object->setDisappeared(new \DateTime());
        }

        return $object;
    }

    protected function extractData($object, array $context): array
    {
        return [
            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_DATE_APPARITION => $object->getAppeared(),
            self::ATTR_ID_RFID_CODE_BARRE => $object->getIdentifier(),
            self::TAG_NOTES => $object->getNotes(),
        ];
    }
}
