<?php

declare(strict_types=1);

/*
 * Chill is a software for social workers
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Chill\MainBundle\Doctrine\ORM\Hydration;

use Doctrine\ORM\Internal\Hydration\ObjectHydrator;

final class FlatHierarchyEntityHydrator extends ObjectHydrator
{
    public const LIST = 'chill_flat_hierarchy_list';

    protected function hydrateAllData()
    {
        return array_values(iterator_to_array($this->flatListGenerator($this->buildChildrenHashmap(parent::hydrateAllData()))));
    }

    private function buildChildrenHashmap(array $nodes): array
    {
        return array_reduce(
            $nodes,
            static function (array $collect, $node): array {
                $parentId = (null === $parent = $node->getParent()) ?
                    null :
                    spl_object_id($parent);

                $collect[$parentId][] = $node;

                return $collect;
            },
            []
        );
    }

    private function flatListGenerator(array $hashMap, ?object $parent = null): \Generator
    {
        $parent = null === $parent ? null : spl_object_id($parent);
        $hashMap += [$parent => []];

        foreach ($hashMap[$parent] as $node) {
            yield spl_object_id($node) => $node;

            yield from $this->flatListGenerator($hashMap, $node);
        }
    }
}
