<?php

/*
 * @author TRYDEA - 2024
 */

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

use Shared\Authentication\Entity\IdentifiedEntity;
use Webapp\Core\Entity\AbstractVariable;
use Webapp\Core\Entity\Measure;
use Webapp\Core\Entity\StateCode;
use Webapp\FileManagement\Dto\Webapp\MeasureDto;
use Webapp\FileManagement\Exception\ParsingException;
use Webapp\FileManagement\Service\XmlUtils\Normalizer\AbstractXmlNormalizer;
use Webapp\FileManagement\Service\XmlUtils\Normalizer\XmlImportConfig;
use Webapp\FileManagement\Service\XmlUtils\ReferenceContext;

/**
 * @template-extends AbstractXmlNormalizer<MeasureDto, MeasureDtoXmlDto>
 *
 * @psalm-type MeasureDtoXmlDto = array{
 *  "@codeEtat": ?StateCode,
 *  "@horodatage": \DateTime,
 *  "@indiceGeneratrice": ?int,
 *  "@mesureGeneratrice": ?string,
 *  "@mesuresGenerees": ?string,
 *  "@objetMetier": ?IdentifiedEntity,
 *  "@valeur": ?string,
 *  "@variable": ?AbstractVariable,
 *  "@xsi:type": ?string
 *  }
 */
class MeasureDtoNormalizer extends AbstractXmlNormalizer
{
    protected const ATTR_OBJET_METIER = '@objetMetier';
    protected const ATTR_CODE_ETAT = '@codeEtat';
    protected const ATTR_VALEUR = '@valeur';
    protected const ATTR_INDICE_GENERATRICE = '@indiceGeneratrice';
    protected const ATTR_MESURE_GENERATRICE = '@mesureGeneratrice';
    protected const ATTR_VARIABLE = '@variable';
    protected const ATTR_MESURES_GENEREES = '@mesuresGenerees';
    private const ATTR_HORODATAGE = '@horodatage';

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

    protected function extractData($object, array $context): array
    {
        throw new \LogicException('Method not implemented');
    }

    protected function getImportDataConfig(array $context): array
    {
        return [
            self::ATTR_XSI_TYPE => 'string',
            self::ATTR_CODE_ETAT => XmlImportConfig::reference(StateCode::class),
            self::ATTR_VALEUR => 'string',
            self::ATTR_INDICE_GENERATRICE => 'int',
            self::ATTR_MESURE_GENERATRICE => 'string',
            self::ATTR_MESURES_GENEREES => 'string',
            self::ATTR_VARIABLE => XmlImportConfig::reference(AbstractVariable::class),
            self::ATTR_OBJET_METIER => XmlImportConfig::reference(IdentifiedEntity::class),
            self::ATTR_HORODATAGE => \DateTime::class,
        ];
    }

    protected function validateImportData($data, array $context): void
    {
        if (($data[self::ATTR_HORODATAGE] ?? '') === '') {
            throw new ParsingException('Missing timestamp in measure.');
        }
    }

    protected function generateImportedObject($data, array $context): MeasureDto
    {
        $measure = new Measure();
        $readerHelper = self::getReaderHelper($context);
        $referenceContext = $context[self::REFERENCE];
        \assert($referenceContext instanceof ReferenceContext);
        $readerHelper->add($referenceContext->getReference(), $measure);

        return new MeasureDto($measure);
    }

    protected function completeImportedObject($object, $data, ?string $format, array $context)
    {
        $object->measure
            ->setState($data[self::ATTR_CODE_ETAT])
            ->setTimestamp($data[self::ATTR_HORODATAGE]);

        if ('adonis.modeleMetier.saisieTerrain:MesureVariableBooleen' === $data[self::ATTR_XSI_TYPE]) {
            $value = null !== $data[self::ATTR_VALEUR] ? 'true' : 'false';
        } else {
            $value = $data[self::ATTR_VALEUR];
        }
        $object->measure->setValue($value);

        $object->codeEtat = $data[self::ATTR_CODE_ETAT];
        $object->valeur = $data[self::ATTR_VALEUR];
        $object->indiceGeneratrice = $data[self::ATTR_INDICE_GENERATRICE];
        $object->mesureGeneratrice = $data[self::ATTR_MESURE_GENERATRICE];
        $object->mesuresGenerees = $data[self::ATTR_MESURES_GENEREES];
        $object->variable = $data[self::ATTR_VARIABLE];
        $object->objetMetier = $data[self::ATTR_OBJET_METIER];

        return $object;
    }
}
