<?php declare(strict_types=1);

namespace Newland\Toubiz\Sync\Neos\Domain\TypeConverter;

use Neos\Flow\ObjectManagement\ObjectManager;
use Neos\Flow\Persistence\Doctrine\Repository;
use Neos\Flow\Property\Exception\TargetNotFoundException;
use Neos\Flow\Property\PropertyMappingConfigurationInterface;
use Neos\Flow\Property\TypeConverter\AbstractTypeConverter;
use Newland\Toubiz\Sync\Neos\Translation\TranslatableRepositoryInterface;

/**
 * Super class for common entity type converter logic.
 * All concrete converters that convert from a persistence_object_identifier to an entity instance
 * should extend from this class.
 *
 * All they have to do is inject to correct concrete repository as $repository.
 */
abstract class EntityTypeConverter extends AbstractTypeConverter
{
    protected $sourceTypes = [ 'string' ];
    protected $priority = 99;

    /** @var Repository */
    protected $repository;

    public function initializeObject(): void
    {
        $this->targetType = $this->repository->getEntityClassName();
    }

    public function convertFrom(
        $source,
        $targetType,
        array $convertedChildProperties = [],
        PropertyMappingConfigurationInterface $configuration = null
    ) {
        if ($this->repository instanceof TranslatableRepositoryInterface) {
            // This is a hack. The language might not be initialized at this point.
            // But entities have unique ids across languages, so it shouldn't be a problem.
            $entity = $this->repository->withoutLanguageHandling(
                function () use ($source) {
                    return $this->repository->findByIdentifier((string) $source);
                }
            );
        } else {
            $entity = $this->repository->findByIdentifier((string) $source);
        }

        if ($entity === null) {
            throw new TargetNotFoundException('No record with identifier ' . $source . ' found.');
        }

        return $entity;
    }
}
