<?php

/*
 * @author TRYDEA - 2024
 */

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

use Shared\Authentication\Entity\IdentifiedEntity;
use Webapp\Core\Entity\Annotation;
use Webapp\Core\Entity\Measure;
use Webapp\Core\Enumeration\AnnotationKindEnum;
use Webapp\Core\Enumeration\AnnotationTypeEnum;
use Webapp\FileManagement\Dto\Common\ReferenceDto;
use Webapp\FileManagement\Service\XmlUtils\Normalizer\AbstractXmlNormalizer;
use Webapp\FileManagement\Service\XmlUtils\Normalizer\XmlImportConfig;

/**
 * @template-extends AbstractXmlNormalizer<Annotation, AnnotationXmlDto>
 *
 * @psalm-type AnnotationXmlDto = array{
 *      "@date": ?\DateTime,
 *      "@donnee": ?string,
 *      "@mesureVariable": ?Measure,
 *      "@nature": ?string,
 *      "@objetMetier": ?IdentifiedEntity
 * }
 */
class AnnotationNormalizer extends AbstractXmlNormalizer
{
    protected const ATTR_NOM = '@nom';
    protected const ATTR_MESURE_VARIABLE = '@mesureVariable';
    protected const ATTR_OBJET_METIER = '@objetMetier';
    protected const ATTR_NATURE = '@nature';
    protected const ATTR_DONNEE = '@donnee';
    protected const ATTR_DATE = '@date';
    protected const TAG_CATEGORIE = 'categorie';
    protected const TAG_MOTSCLES = 'motscles';

    public const TYPE_TEXTE = 'texte';
    public const TYPE_PHOTO = 'photo';
    public const TYPE_SON = 'son';

    public const REVERSE_TYPE_MAP = [
        self::TYPE_TEXTE => AnnotationKindEnum::TEXT,
        self::TYPE_PHOTO => AnnotationKindEnum::PICTURE,
        self::TYPE_SON => AnnotationKindEnum::SOUND,
    ];

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

    protected function getImportDataConfig(array $context): array
    {
        return [
            self::ATTR_DONNEE => 'string',
            self::ATTR_DATE => \DateTime::class,
            self::ATTR_MESURE_VARIABLE => XmlImportConfig::reference(Measure::class),
            self::ATTR_OBJET_METIER => XmlImportConfig::reference(IdentifiedEntity::class),
            self::ATTR_NATURE => 'string',
        ];
    }

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

    protected function completeImportedObject($object, $data, ?string $format, array $context): Annotation
    {
        $object
            ->setValue($data[self::ATTR_DONNEE])
            ->setTimestamp($data[self::ATTR_DATE])
            ->setType(self::REVERSE_TYPE_MAP[$data[self::ATTR_NATURE] ?? self::TYPE_SON]);

        if (null !== $data[self::ATTR_MESURE_VARIABLE]) {
            $object->setTarget($data[self::ATTR_MESURE_VARIABLE]);
        } else {
            $object->setTarget($data[self::ATTR_OBJET_METIER]);
        }

        return $object;
    }

    protected function extractData($object, array $context): array
    {
        return [
            self::ATTR_NOM => $object->getName(),
            self::ATTR_MESURE_VARIABLE => null === $object->getTargetType() && null !== $object->getTarget() ? new ReferenceDto($object->getTarget()) : null,
            self::ATTR_OBJET_METIER => null !== $object->getTargetType() && null !== $object->getTarget() ? new ReferenceDto($object->getTarget()) : null,
            self::ATTR_NATURE => AnnotationTypeEnum::ANNOT_TYPE_TEXT === $object->getType() ? self::TYPE_TEXTE : null,
            self::ATTR_DONNEE => AnnotationTypeEnum::ANNOT_TYPE_TEXT === $object->getType() ? $object->getValue() : null,
            self::ATTR_DATE => $object->getTimestamp(),
            self::TAG_CATEGORIE => $object->getCategories(),
            self::TAG_MOTSCLES => $object->getKeywords(),
        ];
    }
}
