<?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 SelectedPages extends SubnodeBasedMarkerProvider
{
    protected $nodeType = 'Newland.Toubiz.Map.Neos:Map.Markers.SelectedPages';

    /**
     * @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
    {
        $pages = array_slice(
            $node->getProperty('pages') ?: [],
            $offset,
            $limit
        );

        $markers = [];
        foreach ($pages as $page) {
            $marker = new Marker(
                $page->getIdentifier(),
                [ (string) $node->findNodePath() ],
                (float) $page->getProperty('toubizMapLongitude'),
                (float) $page->getProperty('toubizMapLatitude'),
                $page->getProperty('title')
            );

            $marker->description = $page->getProperty('toubizMapDescription');
            $marker->url = $this->resolveUri($page) ?: '#';
            $marker->defaultStyle = $this->getStyle($page);

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

            $markers[] = $marker;
        }

        return $markers;
    }

    private function resolveImage(NodeInterface $node): ?array
    {
        /** @var Image|null $imageModel */
        $imageModel = $node->getProperty('toubizMapImage');
        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 = sprintf('node://%s', $node->getIdentifier());

        $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
    {
        return count($node->getProperty('pages') ?: []);
    }
}
