<?php declare(strict_types=1);

namespace Newland\Toubiz\Map\Neos\Provider\DefaultProviders;

use Neos\ContentRepository\Domain\Model\Node;
use Neos\ContentRepository\Domain\Model\NodeInterface;
use Neos\Media\Domain\Model\Image;
use Neos\Media\Domain\Model\ThumbnailConfiguration;
use Neos\Media\Domain\Service\AssetService;
use Newland\NeosCommon\Service\ControllerContextFactory;
use Newland\NeosIcons\IconUrlService;
use Newland\Toubiz\Map\Neos\Provider\Contract\Marker;
use Newland\Toubiz\Map\Neos\Provider\MapDataProvider;
use Newland\Toubiz\Map\Neos\Service\FusionSnippetRenderer;
use Neos\Flow\Annotations as Flow;

/**
 * @MapDataProvider()
 */
class Links extends SubnodeBasedMarkerProvider
{
    protected $nodeType = 'Newland.Toubiz.Map.Neos:Map.Markers.Link';

    /**
     * @var FusionSnippetRenderer
     * @Flow\Inject()
     */
    protected $snippetRenderer;

    /**
     * @var AssetService
     * @Flow\Inject()
     */
    protected $assetService;

    /**
     * @var ControllerContextFactory
     * @Flow\Inject()
     */
    protected $contextFactory;

    /**
     * @var IconUrlService
     * @Flow\Inject()
     */
    protected $iconUrlService;

    /**
     * @var array
     * @Flow\InjectConfiguration(package="Newland.Toubiz.Map.Neos", path="markers.defaultIcons")
     */
    protected $defaultIconSettings;

    public function markersForNode(Node $node, int $offset, int $limit): array
    {
        // This provider only produces a single marker anyways, so no offset/limit handling is needed.
        $url = $this->resolveUri($node);
        if (!$url) {
            return [];
        }

        $marker = new Marker(
            (string) $node->getIdentifier(),
            [ (string) $node->findNodePath() ],
            (float) $node->getProperty('longitude'),
            (float) $node->getProperty('latitude'),
            (string) $node->getProperty('title')
        );

        $marker->categoryTitle = $node->getProperty('categoryTitle');
        $marker->url = $url;
        $marker->urlTarget = $node->getProperty('uriTarget') ?: null;
        $marker->defaultStyle = $this->getStyle($node);

        $image = $this->resolveImage($node);
        if ($image) {
            $marker->imageUrl = $image['url'];
            $marker->imageAlt = $image['alt'];
        }

        return [ $marker ];
    }

    private function resolveImage(NodeInterface $node): ?array
    {
        /** @var Image|null $imageModel */
        $imageModel = $node->getProperty('image');
        if ($imageModel === null) {
            return null;
        }

        $imageUri = $this->assetService->getThumbnailUriAndSizeForAsset(
            $imageModel,
            new ThumbnailConfiguration(),
            $this->contextFactory->initializeFakeActionRequest($node, [])
        )['src'] ?? null;

        return [
            'url' => $imageUri,
            'alt' => $imageModel->getTitle() ?: $node->getProperty('title'),
        ];
    }

    private function getStyle(NodeInterface $node): array
    {
        $style = [
            'icon' => $node->getProperty('icon') ?? $this->defaultIconSettings['icon'] ?? 'circle-solid',
            'color' => $node->getProperty('color') ?? $this->defaultIconSettings['color'] ?? 'white',
            'backgroundColor' => $node->getProperty('backgroundColor')
                ?? $this->defaultIconSettings['color']
                ?? '#333',
        ];
        $style['iconUrl'] = $this->iconUrlService->buildMarkerIconUrlFromNode($node, $style);
        return $style;
    }

    private function resolveUri(NodeInterface $node): ?string
    {
        $uri = $node->getProperty('uri');
        if (!$uri) {
            return null;
        }

        $url = $this->snippetRenderer->renderSnippet(
            'lib.newland.toubiz.map.neos.convertUris',
            [ 'value' => $uri ],
            $node
        );
        if (!$url) {
            return null;
        }

        return $url;
    }

    public function numberOfMarkersForNode(Node $node): int
    {
        $url = $this->resolveUri($node);
        return $url ? 1 : 0;
    }
}
