<?php

namespace Src\Modules\JsonObjects\Application;

use Src\Modules\JsonObjects\Interfaces\Application\IFactory;
use Src\Modules\JsonObjects\Interfaces\IFactory as IModuleFactory;
use Src\Modules\JsonObjects\Interfaces\Application\IValidator;
use Src\Modules\JsonObjects\Interfaces\Application\IDomain;
use Src\Modules\JsonObjects\Interfaces\Application\IDataBuilder;

class Factory implements IFactory
{

    protected IModuleFactory $moduleFactory;

    protected ?IDomain $domain = null;

    protected ?FilesBrowser $filesBrowser = null;

    protected array $conf;

    public function init(array $conf = []): void
    {
        $this->conf = [
            'validator' => Validator::class,
            'dataBuilder' => DataBuilder::class,
            'domain' => Domain::class,
            'filesBrowser' => FilesBrowser::class,
        ];
        $this->conf = array_replace_recursive($this->conf, $conf);
    }

    protected function createInstance($instance)
    {
        if (gettype($instance) == 'string') {
            return new $instance;
        }
        if (gettype($instance) == 'object') {
            return $instance;
        }
    }

    public function setModuleFactory(IModuleFactory $factorory): void
    {
        $this->moduleFactory = $factorory;
    }

    public function getModuleFactory(): IModuleFactory
    {
        return $this->moduleFactory;
    }

    protected function createValidator(): Validator
    {
        return $this->createInstance($this->conf['validator']);
    }

    protected function creteDataBuilder(): DataBuilder
    {
        $dataBuilder = $this->createInstance($this->conf['dataBuilder']);
        $storage = $this->moduleFactory->getInfrastructureFactory()->getDirsStorage();
        $dataBuilder->setDirStorage($storage);
        return $dataBuilder;
    }

    public function getDomain(): Domain
    {
        if ($this->domain === null) {
            $this->domain = $this->createInstance($this->conf['domain']);
            $validator = $this->createValidator();
            $this->domain->setValidator($validator);
            $dtoFactory = $this->moduleFactory->getDtoFactory();
            $this->domain->setDtoFactory($dtoFactory);
            $persistLayer = $this->moduleFactory->getInfrastructureFactory()->getPersistLayer();
            $this->domain->setPersistLayer($persistLayer);
            $storage = $this->moduleFactory->getInfrastructureFactory()->getStorage();
            $this->domain->setStorage($storage);
            $dataBuilder = $this->creteDataBuilder();
            $this->domain->setDataBuilder($dataBuilder);
            $dirStorage = $this->moduleFactory->getInfrastructureFactory()->getDirsStorage();
            $this->domain->setDirStorage($dirStorage);
            $dirsPersistLayer = $this->moduleFactory->getInfrastructureFactory()->getDirsPersistLayer();
            $this->domain->setDirsPersistLayer($dirsPersistLayer);
        }
        return $this->domain;
    }

    public function getFilesBrowser(): FilesBrowser
    {
        if ($this->filesBrowser === null) {
            $this->filesBrowser = $this->createInstance($this->conf['filesBrowser']);
        }
        return $this->filesBrowser;
    }
}
