<?php
namespace Studip;

use Flexi\Template;
use Stringable;

final class VueApp implements Stringable
{
    public static function create(string $base_component): VueApp
    {
        return new self($base_component);
    }

    private array $components = [];
    private array $props = [];
    private array $stores = [];
    private array $storeData = [];

    private function __construct(private readonly string $base_component) {
    }

    public function withComponents(string ...$components): VueApp
    {
        $clone = clone $this;
        foreach ($components as $component) {
            $clone = $clone->withAddedComponent($component);
        }
        return $clone;
    }

    public function withAddedComponent(string $component): VueApp
    {
        $clone = clone $this;
        if (!in_array($component, $clone->components)) {
            $clone->components[] = $component;
        }
        return $clone;
    }

    public function getBaseComponent(): string
    {
        return $this->base_component;
    }

    public function withProps(array $props): VueApp
    {
        $clone = clone $this;
        $clone->props = $props;
        return $clone;
    }

    public function getProps(): array
    {
        return $this->props;
    }

    public function withStore(?string $store, ?string $index = null, ?array $data = null): VueApp
    {
        $clone = clone $this;

        $clone->stores[$index ?? $store] = $store;

        if ($data !== null) {
            $clone->storeData[$index ?? $store] = $data;
        }

        return $clone;
    }

    public function getStores(): array
    {
        return $this->stores;
    }

    public function getStoreData(): array
    {
        return $this->storeData;
    }

    public function getTemplate(): Template
    {
        $template = $GLOBALS['template_factory']->open('vue-app.php');
        $template->attributes = [
            'data-vue-app' => json_encode([
                'components' => [
                    $this->base_component,
                    ...$this->components
                ],
                'stores' => $this->stores,
            ]),
            'is' => basename($this->base_component),

            ...$this->getPreparedProps(),
        ];
        $template->storeData = $this->storeData;
        return $template;
    }

    private function getPreparedProps(): array
    {
        $result = [];
        foreach ($this->props as $name => $value) {
            $name = ltrim($name, ':');
            $result[":{$name}"] = json_encode($value);
        }
        return $result;
    }

    public function render(): string
    {
        return $this->getTemplate()->render();
    }

    public function __toString(): string
    {
        return $this->render();
    }
}