<?php

namespace Shm\ShmRPC\ShmRPCCodeGen\CodeGenPhp;

use Shm\ShmTypes\ArrayOfType;
use Shm\ShmTypes\CompositeTypes\VizType\VizType;
use Shm\ShmTypes\EnumType;
use Shm\ShmTypes\StructureType;

class CreateClassResponse
{

    private string $namespace = '';
    private string $dirFiles = '';
    private string $className = '';

    public function __construct(string $namespace, string $dirFiles, string $className)
    {
        $this->namespace = $namespace;
        $this->dirFiles = $dirFiles;
        $this->className = $className;
        //Создаем папку если не существует
        if (!is_dir($this->dirFiles)) {
            mkdir($this->dirFiles, 0777, true);
        }
    }

    public function create(StructureType $structure)
    {


        $class = new \Nette\PhpGenerator\ClassType($this->className);

        //Тело конструктора
        $ctorBody = [];

        //Тело функции data
        $dataBody = [];
        foreach ($structure->items as $key => $item) {

            // Если это viz — пропускаем (настройка аналитики, не поле данных)
            if ($item instanceof VizType) {
                continue;
            }

            if ($item instanceof ArrayOfType && $item->itemType instanceof StructureType) {


                if ($item->itemType->collection) {
                    $className = ucfirst($item->itemType->collection) . 'ResponseItem';
                } else {
                    $className = $this->className . ucfirst($item->itemType->key);
                }

                $createClassResponse = new CreateClassResponse($this->namespace, $this->dirFiles,  $className);
                $createClassResponse->create($item->itemType);

                $class->addProperty($key)->setType('array')->setComment('@var ' . $className . '[]');

                $ctorBody[] = "if(isset(\$values['$key'])){
                    \$this->$key = [];
                    foreach(\$values['$key'] as \$item){
                        \$this->" . $key . "[] = new " . $className . "(\$item);
                    }
                }";

                $dataBody[] = "if(isset(\$this->$key)){
                    \$data['$key'] = [];
                    foreach(\$this->$key as \$item){
                        \$data['$key'][] = \$item->data();
                    }
                }";
            } else if ($item instanceof StructureType) {

                $className = $this->className . ucfirst($key);

                $createClassResponse = new CreateClassResponse($this->namespace, $this->dirFiles,  $className);
                $createClassResponse->create($item);

                $class->addProperty($key)->setType($className);

                $ctorBody[] = "if(isset(\$values['$key'])){
                    \$this->$key = new " . $className . "(\$values['$key']);
                }";

                $dataBody[] = "if(isset(\$this->$key)){
                    \$data['$key'] = \$this->" . $key . "->data();
                }";
            } else {


                $type = $item->type;
                $type = TypeToPhp::convert($type);
                if ($item instanceof EnumType) {

                    $createEnum = new CreateEnum($this->namespace, $this->dirFiles, $item->key . 'Enum');
                    $type = $createEnum->create($item);
                }

                $class->addProperty($key)->setType($type);

                $ctorBody[] = "if(isset(\$values['$key'])){
                    \$this->$key = \$values['$key'];
                }";
                $dataBody[] = "if(isset(\$this->$key)){
                    \$data['$key'] = \$this->$key;
                }";
            }
        }

        //Конструтор который принимает массив значений и подвтяеляет те что есть
        $ctor = $class->addMethod('__construct');
        $ctor->addParameter('values')->setType('array');



        $ctor->setBody(implode("\n", $ctorBody));


        //Добаляем функцию которая возвращает все значения в виде массива ключ => значение
        $method = $class->addMethod('data');
        $method->setReturnType('array');




        $method->setBody('$data = []; ' . implode(' ', $dataBody) . ' return $data;');

        $output = "<?php\n\n"; // заголовок файла
        $output .= "namespace " . $this->namespace . ";\n";

        $output .= $class . "\n\n"; // собираем все классы

        $filePath = $this->dirFiles . $this->className . '.php';
        file_put_contents($filePath, $output);
    }
}