<?php
namespace Newland\Toubiz\Poi\Neos\PageFrame;

use Neos\ContentRepository\Domain\Model\NodeInterface;
use Neos\Eel\FlowQuery\FlowQuery;
use Neos\Flow\Annotations as Flow;
use Neos\Neos\TypeConverter\EntityToIdentityConverter;
use Newland\PageFrameProvider\Definition\RoutingConfigurationHelper;
use Newland\PageFrameProvider\Breadcrumb\BreadcrumbProvider;
use Newland\PageFrameProvider\Service\PageFrameContextService;
use Newland\Toubiz\Sync\Neos\Domain\Model\Article;
use Newland\Toubiz\Sync\Neos\Domain\Repository\ArticleRepository;

class ArticleBreadcrumbProvider implements BreadcrumbProvider
{

    /**
     * @var PageFrameContextService
     * @Flow\Inject()
     */
    protected $pageFrameContext;

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

    /**
     * @var array
     * @Flow\InjectConfiguration(package="Newland.Toubiz.Poi.Neos", path="detailPage")
     */
    protected $typeConfiguration;

    /**
     * @var RoutingConfigurationHelper
     * @Flow\Inject()
     */
    protected $configurationHelper;

    /**
     * @param NodeInterface $siteNode
     * @param array $configuration
     * @return NodeInterface[]
     */
    public function selectBreadCrumbs(NodeInterface $siteNode, array $configuration): array
    {
        $this->configurationHelper->setTypeConfiguration($this->typeConfiguration);
        $article = $this->getArticle();
        if (!$article) {
            return [];
        }

        $definition = $this->configurationHelper->getDefinition((string) $article->getMainType());
        if (!$definition) {
            return [];
        }

        $breadcrumb = $definition->getBreadcrumb($siteNode->getName());
        if (empty($breadcrumb)) {
            return [];
        }

        $selector = $siteNode->getPath() . ', ' . implode(', ', $breadcrumb);
        return (new FlowQuery([ $siteNode ]))->find($selector)->get();
    }

    private function getArticle(): ?Article
    {
        $articleUid = $this->pageFrameContext->getPluginArguments()['article'] ?? null;
        $articleUid = $this->resolveFlowEntityEncoding($articleUid);
        if (!$articleUid) {
            return null;
        }

        return $this->articleRepository->findOneBy([ 'Persistence_Object_Identifier' => $articleUid ]);
    }

    /**
     * Flow entity encoding (if passing models as arguments) uses an array with the `__identity` key for the uuid.
     * @see EntityToIdentityConverter
     *
     * @param string|array|null $articleUid
     * @return string|null
     */
    private function resolveFlowEntityEncoding($articleUid): ?string
    {
        if (\is_string($articleUid) || $articleUid === null) {
            return $articleUid;
        }

        if (\is_array($articleUid) && array_key_exists('__identity', $articleUid)) {
            return $articleUid['__identity'];
        }

        return null;
    }
}
