<?php

namespace kernel;

use RuntimeException;

class AssetsCollector
{
    protected array $assetsPool = [];

    public function registerAsset(Assets $assets): void
    {
        $this->assetsPool[] = $assets;
    }

    public function renderCss(): void
    {
        $css = [];
        foreach ($this->assetsPool as $item) {
            /** @var Assets $item */
            $css = array_merge($css, $item->getCollectorCss());
        }

        try {
            $sortedStyles = $this->sortStyles($css);

            // Выводим отсортированные стили
            foreach ($sortedStyles as $style) {
                echo '<link rel="stylesheet" href="' . htmlspecialchars($style) . '">' . "\n";
            }
        } catch (RuntimeException $e) {
            echo 'Ошибка: ' . $e->getMessage();
        }
    }

    public function renderJs(bool $body = true): void
    {
        $scripts = [];
        foreach ($this->assetsPool as $item) {
            /** @var Assets $item */
            $scripts = array_merge($scripts, $item->getCollectorJs());
        }

        try {
            $sortedScripts = $this->sortScripts($scripts);

            // Разделяем скрипты для head и body
            $headScripts = [];
            $bodyScripts = [];

            foreach ($sortedScripts as $script) {
                if ($script['body']) {
                    $bodyScripts[] = $script['resource'];
                } else {
                    $headScripts[] = $script['resource'];
                }
            }

            // Выводим скрипты для head
            if ($body){
                $scriptsToRender = $bodyScripts;
            }
            else {
                $scriptsToRender = $headScripts;
            }
            foreach ($scriptsToRender as $script) {
                echo '<script src="' . htmlspecialchars($script) . '"></script>' . "\n";
            }
        }
        catch (RuntimeException $e) {
            echo 'Ошибка: ' . $e->getMessage();
        }
    }

    protected function sortStyles(array $styles): array
    {
        $sorted = [];
        $added = [];

        // Пока не добавим все стили
        while (count($sorted) < count($styles)) {
            $found = false;

            foreach ($styles as $name => $style) {
                // Если стиль еще не добавлен и его зависимости выполнены
                if (!isset($added[$name]) &&
                    (empty($style['after']) || isset($added[$style['after']]))) {
                    $sorted[] = $style['resource'];
                    $added[$name] = true;
                    $found = true;
                }
            }

            if (!$found) {
                // Если есть циклическая зависимость
                throw new RuntimeException('Обнаружена циклическая зависимость в стилях');
            }
        }

        return $sorted;
    }

    protected function sortScripts(array $scripts): array
    {
        $sorted = [];
        $added = [];

        while (count($sorted) < count($scripts)) {
            $found = false;

            foreach ($scripts as $name => $script) {
                if (!isset($added[$name]) &&
                    (empty($script['after']) || isset($added[$script['after']]))) {
                    $sorted[] = $script;
                    $added[$name] = true;
                    $found = true;
                }
            }

            if (!$found) {
                throw new RuntimeException('Обнаружена циклическая зависимость в скриптах');
            }
        }

        return $sorted;
    }

}