<?php declare(strict_types=1);

namespace Newland\Toubiz\Events\Neos;

use Neos\Flow\Annotations as Flow;
use Newland\Toubiz\Common\Neos\Translation\TranslatesNodeProperties;
use Newland\Toubiz\Sync\Neos\Domain\Model\Article;
use Newland\Toubiz\Sync\Neos\Domain\Model\Category;
use Newland\Toubiz\Sync\Neos\Domain\Model\Event;
use Newland\Toubiz\Sync\Neos\Domain\Repository\ArticleRepository;
use Newland\Toubiz\Sync\Neos\Domain\Repository\CategoryRepository;
use Newland\Toubiz\Sync\Neos\Domain\Repository\EventRepository;

class TranslateNodeProperties
{

    /**
     * @var EventRepository
     * @Flow\Inject()
     */
    protected $eventRepository;

    /**
     * @var CategoryRepository
     * @Flow\Inject()
     */
    protected $categoryRepository;

    /**
     * @var ArticleRepository
     * @Flow\Inject()
     */
    protected $articleRepository;

    /**
     * @TranslatesNodeProperties(nodeTypes={"Newland.Toubiz.Events.Neos:Teaser"})
     */
    public function translateSingleReferences(array $properties, string $targetLanguage): array
    {
        $translated = $this->translateEvent($properties['event'] ?? null, $targetLanguage);
        if ($translated) {
            $properties['event'] = $translated;
        } else {
            unset($properties['event']);
        }

        return $properties;
    }

    /**
     * @TranslatesNodeProperties(
     *     nodeTypes={
     *          "Newland.Toubiz.Events.Neos:List",
     *          "Newland.Toubiz.Events.Neos:TeaserList",
     *      }
     * )
     */
    public function translatePreselectedCategories(array $properties, string $targetLanguage): array
    {
        $properties['preselectedCategories'] = array_values(array_filter(array_map(
            function (string $id) use ($targetLanguage) {
                return $this->translateCategory($id, $targetLanguage);
            },
            $properties['preselectedCategories'] ?? []
        )));

        return $properties;
    }

    /**
     * @TranslatesNodeProperties(nodeTypes={"Newland.Toubiz.Events.Neos:List"})
     */
    public function translatePreselectedCities(array $properties, string $targetLanguage): array
    {
        $properties['preselectedCities'] = array_values(array_filter(array_map(
            function (string $id) use ($targetLanguage) {
                return $this->translateArticle($id, $targetLanguage);
            },
            $properties['preselectedCities'] ?? []
        )));

        return $properties;
    }


    private function translateEvent(
        ?string $id,
        string $targetLanguage
    ): ?string {
        if ($id === null) {
            return null;
        }
        $event = $this->eventRepository->withoutLanguageHandling(function () use ($id) {
            return $this->eventRepository->findByIdentifier($id);
        });

        if (!$event) {
            return null;
        }

        $languageVariant = $this->eventRepository->translateInto($event, $targetLanguage);

        if ($languageVariant instanceof Event) {
            return $languageVariant->getPersistenceObjectIdentifier();
        }

        return null;
    }


    private function translateCategory(
        string $id,
        string $targetLanguage
    ): ?string {
        $category = $this->categoryRepository->withoutLanguageHandling(function () use ($id) {
            return $this->categoryRepository->findByIdentifier($id);
        });

        if (!$category) {
            return null;
        }

        $languageVariant = $this->categoryRepository->translateInto($category, $targetLanguage);

        if ($languageVariant instanceof Category) {
            return $languageVariant->getPersistenceObjectIdentifier();
        }

        return null;
    }


    private function translateArticle(
        string $id,
        string $targetLanguage
    ): ?string {
        $article = $this->articleRepository->withoutLanguageHandling(function () use ($id) {
            return $this->articleRepository->findByIdentifier($id);
        });

        if (!$article) {
            return null;
        }

        $languageVariant = $this->articleRepository->translateInto($article, $targetLanguage);

        if ($languageVariant instanceof Article) {
            return $languageVariant->getPersistenceObjectIdentifier();
        }

        return null;
    }
}
