<?php

namespace Src\Common;

use Src\Common\Interfaces\IFactory;
use Src\Common\Interfaces\Pages\IFactory as IPagesFactory;
use Src\Common\Pages\Factory as PagesFactory;
use Src\Common\Interfaces\Dto\IFactory as IDtoFactory;
use Src\Common\Dto\Factory as DtoFactory;
use Src\Common\Interfaces\Application\IFilesBrowser;
use Src\Common\Application\FilesBrowser;

/**
 * Главная фабрика приложения, реализующая паттерн "Абстрактная фабрика".
 * Создает и управляет другими фабриками и сервисами приложения.
 */
class Factory implements IFactory
{

    /**
     * Конфигурация для создания фабрик и сервисов
     * @var array
     */
    protected array $conf;

    /**
     * Фабрика для создания страниц
     * @var IPagesFactory|null
     */
    protected ?IPagesFactory $pagesFactory = null;

    /**
     * Фабрика для создания DTO объектов
     * @var IDtoFactory|null
     */
    protected ?IDtoFactory $dtoFactory = null;

    /**
     * Сервис для работы с файловой системой
     * @var IFilesBrowser|null
     */
    protected ?IFilesBrowser $filesBrowser = null;

    /**
     * Инициализирует фабрику с конфигурацией
     * @param array $conf Дополнительная конфигурация для переопределения стандартной
     */
    public function init(array $conf = []): void
    {
        // Базовая конфигурация по умолчанию
        $this->conf[IPagesFactory::class] = [
            'class' => PagesFactory::class,  // Класс фабрики страниц
            'conf' => [],                    // Конфигурация для фабрики страниц
        ];

        $this->conf[IDtoFactory::class] = [
            'class' => DtoFactory::class,    // Класс фабрики DTO
            'conf' => [],                    // Конфигурация для фабрики DTO
        ];

        $this->conf[IFilesBrowser::class] = [
            'class' => FilesBrowser::class,  // Класс сервиса работы с файлами
            'conf' => [],                   // Конфигурация для сервиса
        ];

        // Объединение с переданной конфигурацией (переопределяет значения по умолчанию)
        $this->conf = array_replace_recursive($this->conf, $conf);
    }

    /**
     * Возвращает фабрику страниц (ленивая инициализация)
     * @return PagesFactory
     */
    public function getPagesFactory(): PagesFactory
    {
        if ($this->pagesFactory === null) {
            // Создаем экземпляр фабрики страниц
            $this->pagesFactory = new $this->conf[IPagesFactory::class]['class'];
            // Инициализируем фабрику с конфигурацией
            $this->pagesFactory->init($this->conf[IPagesFactory::class]['conf']);
        }
        return $this->pagesFactory;
    }

    /**
     * Возвращает фабрику DTO (ленивая инициализация)
     * @return DtoFactory
     */
    public function getDtoFactory(): DtoFactory
    {
        if ($this->dtoFactory === null) {
            // Создаем экземпляр фабрики DTO
            $this->dtoFactory = new $this->conf[IDtoFactory::class]['class'];
            // Инициализируем фабрику с конфигурацией
            $this->dtoFactory->init($this->conf[IDtoFactory::class]['conf']);
        }
        return $this->dtoFactory;
    }

    /**
     * Возвращает сервис для работы с файлами (ленивая инициализация)
     * @return FilesBrowser
     */
    public function getFilesBrowser(): FilesBrowser
    {
        if ($this->filesBrowser === null) {
            // Создаем экземпляр сервиса работы с файлами
            $this->filesBrowser = new $this->conf[IFilesBrowser::class]['class'];
            // Инициализируем сервис с конфигурацией
            $this->filesBrowser->init($this->conf[IFilesBrowser::class]['conf']);
        }
        return $this->filesBrowser;
    }
}
