<?php

declare(strict_types=1);

namespace NoahVet\Reef\Mapper;

use Symfony\Component\Serializer\Encoder\EncoderInterface;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
use Symfony\Component\Serializer\Normalizer\BackedEnumNormalizer;
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Normalizer\UidNormalizer;
use Symfony\Component\Serializer\Serializer;

abstract class AbstractMapper implements MapperInterface
{
    protected string $baseUrl;

    protected string $locale;

    protected Serializer $serializer;

    public function setBaseUrl(string $baseUrl): self
    {
        $this->baseUrl = $baseUrl;

        return $this;
    }

    public function setLocale(string $locale): self
    {
        $this->locale = $locale;

        return $this;
    }

    /**
     * @param array<NormalizerInterface> $normalizers
     * @param array<EncoderInterface>    $encoders
     *
     * @return $this
     */
    protected function initSerializer(
        array $normalizers = [],
        array $encoders = [],
        ?ClassMetadataFactoryInterface $classMetadataFactory = null,
        ?string $timezone = 'UTC',
    ): self {
        $this->serializer = new Serializer(
            \array_merge(
                $normalizers,
                [
                    new DateTimeNormalizer([DateTimeNormalizer::TIMEZONE_KEY => $timezone]),
                    new BackedEnumNormalizer(),
                    new UidNormalizer(),
                    new ArrayDenormalizer(),
                    new ObjectNormalizer($classMetadataFactory),
                    new GetSetMethodNormalizer(),
                ],
            ),
            \array_merge(
                $encoders,
                [
                    new JsonEncoder(),
                ],
            ),
        );

        return $this;
    }
}
