<?php

declare(strict_types=1);

namespace apexl\Io\factories;

use DI\Container;
use DI\ContainerBuilder;

final class ContainerFactory
{
    public function make(string $baseDir, string $containerClass = Container::class): Container
    {
        return new ContainerBuilder($containerClass)->addDefinitions([
            ...$this->coreDefinitions(),
            ...$this->moduleDefinitions($baseDir),
        ])->build();
    }

    private function coreDefinitions(): array
    {
        return [];
    }

    private function moduleDefinitions(string $baseDir): array
    {
        $definitionFiles = [
            ...glob($baseDir . '/module/*/services.php'),
            ...$this->globstar($baseDir . '/vendor/apexl/**/modules/*/services.php')
        ];

        $definitions = [];

        foreach ($definitionFiles as $definitionFile) {
            $definitions = [
                ...$definitions,
                ...require $definitionFile,
            ];
        }

        return $definitions;
    }

    private function globstar($pattern, $flags = 0): array
    {
        if (stripos($pattern, '**') === false) {
            $files = glob($pattern, $flags);
        } else {
            $position = stripos($pattern, '**');
            $rootPattern = substr($pattern, 0, $position - 1);
            $restPattern = substr($pattern, $position + 2);
            $patterns = array ($rootPattern . $restPattern);
            $rootPattern .= '/*';
            while ($dirs = glob($rootPattern, GLOB_ONLYDIR)) {
                $rootPattern .= '/*';
                foreach ($dirs as $dir) {
                    $patterns[] = $dir . $restPattern;
                }
            }
            $files = array ();
            foreach ($patterns as $pat) {
                $files = array_merge($files, $this->globstar($pat, $flags));
            }
        }
        $files = array_unique($files);
        sort($files);
        return $files;
    }

}