<?php

declare(strict_types=1);

namespace VK;

use Exception;
use VK\Robots\RobotAbstract;
use VK\Browsers\BrowserAbstract;
use VK\Proxies\ProxyAbstract;
use VK\Captchas\CaptchaAbstract;
use VK\Loggers\Jasmo;

/**
 * Сборщик
 * 
 * @package Builder
 * @author Arsen Mirzaev
 */
class Builder
{
    /**
     * Собираемый объект
     * 
     * @var object
     */
    private object $target;

    /**
     * Параметры для сборки
     * 
     * @var array
     */
    private array $params;

    public function __construct(array $params = [])
    {
        $this->params = $params;

        return $this;
    }

    /**
     * Сборщик роботов (паттерн: factory)
     * 
     * Проверка существования получившегося класса и запись в свойство ядра
     * 
     * @return object
     */
    public function robot($robot = null): object
    {
        // Ищет по словарю и подставляет имя метода вместо отправленного идентификатора
        if (is_int($robot = (int) ($robot ?? $_ENV['DEFAULT_ROBOT_TYPE'])))
            $robot = $this->convert('robot', $robot);
        if (class_exists($robot_class = __NAMESPACE__ . '\\Robots\\' . ucfirst($robot))) {
            $this->target = new $robot_class($robot);
        } else {
            throw new Exception("Неизвестный тип робота");
        }

        // Присвоение параметров из сборщика в экземпляр класса робота
        foreach (array_keys(get_class_vars($robot_class)) as $key => $value)
        {
            if ($value !== null && isset($this->params[$key]))
            {
                $this->target->$value = $this->params[$key];
            }
        }

        // Добавление в регистр, установка идентификатора и обновление счётчика
        if (false !== Core::set($this->target->setID(Core::$robots_amount++), $this->target)) return $this->target;
        else throw new Exception('Ошибка при сборке робота "Group"');
    }

    /**
     * Конвертер идентификаторов в значения
     * 
     * Используется конструкция if из-за строгого сравнения
     * 
     * @param string $var Словарь идентификаторов
     * @param int $number Идентификатор
     * @return string
     */
    private function convert(string $var, int $number): string
    {
        if ($var === 'robot') {
            if ($number === 0) {
                return 'Group';
            } else if ($number === 1) {
                return 'Account';
            } else throw new Exception('Неизвестный идентификатор робота');
        } else throw new Exception('Неизвестный тип словаря');
    }

    
    /**
     * Установка журналирования
     * 
     * @todo Добавить установку иного журналиста по спецификации PSR-3
     * @return RobotAbstract
     */
    public function log($file = null): Builder
    {
        Jasmo::init()::post($file)::postErrorHandler()::postShutdownHandler();

        return $this;
    }

    /**
     * Установка браузера
     * 
     * @return RobotAbstract
     */
    public function browser(BrowserAbstract $browser): Builder
    {
        $this->browser = $browser;
        return $this;
    }

    /**
     * Установка прокси
     * 
     * @return RobotAbstract
     */
    public function proxy(ProxyAbstract $proxy): Builder
    {
        $this->proxy = $proxy;
        return $this;
    }

    /**
     * Установка обработчика капч
     * 
     * @return RobotAbstract
     */
    public function captcha(CaptchaAbstract $captcha): Builder
    {
        $this->captcha = $captcha;
        return $this;
    }
}