<?php declare(strict_types=1);

namespace Newland\Toubiz\Map\Neos\Tests\Unit\Serialization\Markers;

use Neos\ContentRepository\Domain\Model\Node;
use Neos\Flow\Tests\FunctionalTestCase;
use Neos\Neos\Domain\Model\Site;
use Newland\NeosTestingHelpers\InteractsWithNodes;
use Newland\Toubiz\Map\Neos\Provider\Contract\FilterItem;
use Newland\Toubiz\Map\Neos\Provider\Contract\ProviderContext;
use Newland\Toubiz\Map\Neos\Provider\DefaultProviders\NodeBasedFilterItems;
use Newland\Toubiz\Map\Neos\Provider\DefaultProviders\SubnodeBasedMarkerProvider;

class SubNodeBasedFilterItemsTest extends FunctionalTestCase
{
    protected static $testablePersistenceEnabled = true;
    use InteractsWithNodes;

    /** @var NodeBasedFilterItems */
    protected $subject;

    /** @var Site  */
    protected $site;

    /** @var array<string, Node>  */
    protected $nodes;

    public function setUp(): void
    {
        parent::setUp();

        $this->subject = $this->objectManager->get(NodeBasedFilterItems::class);

        $this->site = $this->initializeSite('foo');
        $this->nodes = $this->nodes(
            [
                '/sites/foo' => [ 'nodeType' => 'Neos.NodeTypes:Page' ],
                '/sites/foo/main' => [ 'nodeType' => 'Neos.Neos:ContentCollection' ],
                '/sites/foo/main/map' => [ 'nodeType' => 'Newland.Toubiz.Map.Neos:Map' ],
                '/sites/foo/main/map/children' => [ 'nodeType' => 'Neos.Neos:ContentCollection' ],
                '/sites/foo/main/map/children/first-filter-item' => [
                    'nodeType' => 'Newland.Toubiz.Map.Neos:Map.FilterItem',
                    'properties' => [ 'title' => 'First Title' ],
                ],
                '/sites/foo/main/map/children/first-filter-item/children' => [ 'nodeType' => 'Neos.Neos:ContentCollection' ],
                '/sites/foo/main/map/children/second-filter-item' => [
                    'nodeType' => 'Newland.Toubiz.Map.Neos:Map.FilterItem',
                    'properties' => [ 'title' => 'Second Title' ],
                ],
                '/sites/foo/main/map/children/second-filter-item/children' => [ 'nodeType' => 'Neos.Neos:ContentCollection' ],
                '/sites/foo/main/map/children/first-filter-item/children/deep-filter-item' => [
                    'nodeType' => 'Newland.Toubiz.Map.Neos:Map.FilterItem',
                    'properties' => [ 'title' => 'Deep Title' ],
                ],
                '/sites/foo/main/map/children/first-filter-item/children/deep-filter-item/children' => [ 'nodeType' => 'Neos.Neos:ContentCollection' ],
            ],
            [
                'site' => $this->site,
                'workspaceName' => 'live',
            ]
        );
    }


    public function testAddsChildrenContainersAsFilterItems(): void
    {
        $firstId = $this->nodes['/sites/foo/main/map/children/first-filter-item']->getIdentifier();
        $secondId = $this->nodes['/sites/foo/main/map/children/second-filter-item']->getIdentifier();
        $deepId = $this->nodes['/sites/foo/main/map/children/first-filter-item/children/deep-filter-item']->getIdentifier();

        $result = $this->subject->getFilterItems(new ProviderContext($this->nodes['/sites/foo/main/map'], null));

        $this->assertEquals(
            '/sites/foo/main/map/children/first-filter-item',
            $result[$firstId]->path,
            'Should have path of first container'
        );
        $this->assertEquals('First Title', $result[$firstId]->title, 'Should have title of first container');

        $this->assertArrayHasKey($secondId, $result, 'Should have array item for second container');
        $this->assertEquals(
            '/sites/foo/main/map/children/second-filter-item',
            $result[$secondId]->path,
            'Should have path of second container'
        );
        $this->assertEquals('Second Title', $result[$secondId]->title, 'Should have title of second container');

        $this->assertArrayHasKey($deepId, $result[$firstId]->children, 'Should have array item for deep container');
        $this->assertEquals(
            '/sites/foo/main/map/children/first-filter-item/children/deep-filter-item',
            $result[$firstId]->children[$deepId]->path,
            'Should have path of deep container'
        );
        $this->assertEquals(
            'Deep Title',
            $result[$firstId]->children[$deepId]->title,
            'Should have title of deep container'
        );
    }

    public function testIgnoresHiddenFilterItems(): void
    {
        $this->nodes['/sites/foo/main/map/children/first-filter-item']->setHidden(true);
        $this->persistNode($this->nodes['/sites/foo/main/map/children/first-filter-item']);
        $firstId = $this->nodes['/sites/foo/main/map/children/first-filter-item']->getIdentifier();
        $childId = $this->nodes['/sites/foo/main/map/children/first-filter-item/children/deep-filter-item']->getIdentifier();

        $result = $this->subject->getFilterItems(new ProviderContext($this->nodes['/sites/foo/main/map'], null));
        $this->assertArrayNotHasKey($firstId, $result);
        $this->assertArrayNotHasKey($childId, $result);
    }

}
