<?php declare(strict_types=1);

namespace Newland\PageFrameProvider\NodeResolution;

use Neos\ContentRepository\Domain\Factory\NodeFactory;
use Neos\ContentRepository\Domain\Model\NodeData;
use Neos\ContentRepository\Domain\Model\NodeInterface;
use Neos\ContentRepository\Domain\Repository\NodeDataRepository;
use Neos\Neos\Domain\Service\ContentContext;
use Neos\Flow\Annotations as Flow;
use function Safe\preg_match;
use function Safe\preg_split;

/**
 * Resolves the root node to the site node of the given reference node.
 */
class SiteNodeResolver implements RootNodeResolver
{

    /**
     * @var NodeDataRepository
     * @Flow\Inject()
     */
    protected $nodeDataRepository;

    /**
     * @var NodeFactory
     * @Flow\Inject()
     */
    protected $nodeFactory;

    public function setConfiguration(array $configuration): void
    {
        // This resolver has no need for configuration.
    }

    /**
     * @param NodeInterface|null $referenceNode
     * @return NodeInterface|null
     */
    public function resolveRootNode(?NodeInterface $referenceNode = null): ?NodeInterface
    {
        if (!$referenceNode) {
            return null;
        }

        return $this->resolveSiteNodeBasedOnContext($referenceNode)
            ?? $this->resolveSiteNodeBasedOnPath($referenceNode);
    }

    private function resolveSiteNodeBasedOnContext(NodeInterface $referenceNode): ?NodeInterface
    {
        $context = $referenceNode->getContext();
        if (!($context instanceof ContentContext)) {
            return null;
        }

        return $context->getCurrentSiteNode();
    }

    private function resolveSiteNodeBasedOnPath(NodeInterface $referenceNode): ?NodeInterface
    {
        preg_match('/^\/sites\/[\w\-_]*/i', $referenceNode->getPath(), $matches);
        $path = $matches[0] ?? null;
        if ($path === null) {
            return null;
        }

        /** @var NodeData|null $data */
        $data = $this->nodeDataRepository->findOneByPath($path, $referenceNode->getWorkspace());
        if ($data === null) {
            return null;
        }

        $node = $this->nodeFactory->createFromNodeData(
            $data,
            $this->nodeFactory->createContextMatchingNodeData($data)
        );

        return $node;
    }

    public function isNodePathAllowed(string $path): bool
    {
        list($path) = preg_split('/[@;]/', $path);
        return (bool) preg_match('/^\/sites\/[\w-]+$/', $path);
    }
}
