<?php

namespace Plainwork\Ui;

use Plainwork\Core\App;
use Plainwork\Http\Request;

class Ui
{
    public $app = App::class;
    private array $renderers = [];
    private bool $isPrintView = false;

    public function isPrintView(): bool
    {
        return $this->isPrintView;
    }

    public function setPrintView(bool $v = true): self
    {
        $this->isPrintView = $v;

        return $this;
    }

    public function render($el, Request $request)
    {
        // if (is_callable($el) or is_array($el)) {
        if (is_array($el)) {
            $ret = $this->app->makeFunc($el);
            $ret = $ret($request);

            return $this->render($ret, $request);
        }

        if (!is_object($el)) {
            return $el;
        }

        $funcs = [];

        $parentClasses = class_parents($el);
        foreach (array_reverse($parentClasses) as $parentClass) {
            $funcs = array_merge($funcs, $this->findRenderers($parentClass));
        }

        $interfaces = class_implements($el);
        foreach ($interfaces as $interface) {
            $funcs = array_merge($funcs, $this->findRenderers($interface));
        }

        $funcs = array_merge($funcs, $this->findRenderers($el));

        if (!$funcs) {
            return $el;
        }

// if (\Plainwork\Ui\Component\Main::class === get_class($el)) {
    // _print_r($funcs);
    // exit;
// }

        $func = $this->app->makePipeline($funcs);

        $ret = $func($el, $request);
        if (is_object($ret)) {
            return $this->render($ret, $request);
        }

        return $ret;
    }

    public function renderer(string $componentClass, $renderFunc): self
    {
        $this->renderers[$componentClass] ??= [];
        $this->renderers[$componentClass][] = $renderFunc;

        return $this;
    }

    private function findRenderers($classOrObject): array
    {
        $ret = [];
        if (is_object($classOrObject) && method_exists($classOrObject, 'render')) {
            $ret[] = [$classOrObject, 'render'];
        }
        $className = is_object($classOrObject) ? get_class($classOrObject) : $classOrObject;

        return array_merge($ret, $this->renderers[$className] ?? []);
    }
}
