<?php
namespace Newland\PageFrameProvider\Breadcrumb;

use Neos\ContentRepository\Domain\Model\NodeInterface;
use Neos\Eel\ProtectedContextAwareInterface;
use Neos\Flow\Annotations as Flow;
use Neos\Flow\Configuration\Exception\InvalidConfigurationException;
use Neos\Flow\ObjectManagement\Exception\InvalidObjectException;
use Neos\Flow\ObjectManagement\ObjectManager;
use Neos\Neos\Domain\Service\ContentContext;
use Newland\PageFrameProvider\Service\PageFrameContextService;

class BreadcrumbEelHelper implements ProtectedContextAwareInterface
{

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

    /**
     * @var ObjectManager
     * @Flow\Inject
     */
    protected $objectManager;

    public function allowsCallOfMethod($methodName)
    {
        return $methodName === 'getBreadcrumbNodes';
    }

    public function getBreadcrumbNodes(NodeInterface $referenceNode): array
    {
        $siteNode = $this->siteNode($referenceNode);
        if (!$siteNode) {
            return [];
        }

        return array_reverse(
            array_filter(
                $this->provider()->selectBreadCrumbs($siteNode, $this->config())
            )
        );
    }

    private function provider(): BreadcrumbProvider
    {
        $config = $this->config();

        $className = NullProvider::class;
        if (array_key_exists('provider', $config)) {
            $className = $config['provider'];
        }

        if (!class_exists($className)) {
            throw new InvalidConfigurationException('No breadcrumb provider ' . $className . ' exists');
        }

        $instance = $this->objectManager->get($className);
        if (!($instance instanceof BreadcrumbProvider)) {
            throw new InvalidObjectException(
                'Breadcrumb providers must implement ' . BreadcrumbProvider::class
                . ' but ' . get_class($instance) . ' does not.'
            );
        }

        return $instance;
    }

    private function config(): array
    {
        return $this->pageFrameContext->getBreadcrumbConfig() ?: [];
    }

    /**
     * @return NodeInterface|null
     */
    private function siteNode(NodeInterface $referenceNode)
    {
        $context = $referenceNode->getContext();
        if (!($context instanceof ContentContext)) {
            return null;
        }
        return $context->getCurrentSiteNode();
    }
}
