<?php

namespace Plainwork\Ui\Renderer;

use Plainwork\Http\Request;
use Plainwork\Ui\Ui;
use Plainwork\Ui\Component\HtmlElement;
use Plainwork\Ui\Component\Dl;
use Plainwork\Ui\Component\Table;
use Plainwork\Ui\Component\Form\AbstractInput;

class DlRenderer
{
    public $ui = Ui::class;
    private static $htmlInputId = 1;

    public function renderDl(Dl $el, bool $isHorizontal, Request $request)
    {
        $class = $isHorizontal ? 'pw-dl-hori' : 'pw-dl-vert';
        $ret = (new HtmlElement('dl'))
            ->withAttr('class', $class)
        ;

        $attr = $el->getAttr();
        foreach ($attr as $k_ => $v_) {
            $ret->withAttr($k_, $v_);
        }

        $items = $el->getItems();
        $ii = 0;
        foreach ($items as list($label, $item)) {
            if ($item instanceof AbstractInput) {
                $label = new HtmlElement('label', $label);
                $htmlId = $item->getAttr('id');
                if (null === $htmlId) {
                    $htmlId = 'pw-input-' . static::$htmlInputId++;
                    $item->withAttr('id', $htmlId);
                }
                $label->withAttr('for', $htmlId);
            }

            if (!is_array($item)) {
                $item = [$item];
            }

            $label = new HtmlElement('dt', $label);
            $labelAttr = $el->getLabelAttr($ii);
            foreach ($labelAttr as $attrName => $attrValue) {
                $label->withAttr($attrName, $attrValue);
            }
            $ret->append($label);

            $valueAttr = $el->getValueAttr($ii);
            foreach ($item as $item2) {
                $v = $this->ui->render($item2, $request);
                if (null === $v) {
                    continue;
                }
                if (!strlen($v)) {
                    continue;
                }

                $v = new HtmlElement('dd', $v);
                foreach ($valueAttr as $attrName => $attrValue) {
                    $v->withAttr($attrName, $attrValue);
                }
                $ret->append($v);
            }

            ++$ii;
        }

        return $ret;
    }

    public function __invoke(Dl $el, Request $request)
    {
        $items = $el->getItems();
        if (!$items) {
            $ret = '';
            return $ret;
        }

        $asTable = $el->isAsTable();

        if (!$asTable) {
            if ($el->isVertical()) {
                return $this->renderDl($el, false, $request);
            } else {
                return $this->renderDl($el, true, $request);
            }
        }

        $ret = new Table();

        $attr = $el->getAttr();
        foreach ($attr as $k_ => $v_) {
            $ret->withAttr($k_, $v_);
        }

        $title = $el->getTitle();
        if (null !== $title) {
            $ret->setCaption($title);
            $titleAttr = $el->getTitleAttr();
            foreach ($titleAttr as $k => $v) {
                $ret->withCaptionAttr($k, $v);
            }
        }

        $head = $el->getHead();
        if ($head) {
            $ret->withHeadCell('head', 'head')->setContent($head[0])->withAttr('scope', 'row');
            $ret->withHeadCell('head', 'content')->setContent($head[1]);
        }

        $i_ = 0;
        foreach ($items as list($label, $item)) {
            $labelAttr = $el->getLabelAttr($i_);
            $valueAttr = $el->getValueAttr($i_);

            ++$i_;
            if (!is_array($item)) {
                $item = [$item];
            }

            $j_ = 0;
            foreach ($item as $item2) {
                $v = $this->ui->render($item2, $request);
                if (null === $v) {
                    continue;
                }
                if (!strlen($v)) {
                    continue;
                }
                ++$j_;
                $rowId = $i_ . '_' . $j_;

                $countItem = count($item);
                if (1 === $j_) {
                    $k = $this->ui->render($label, $request);

                    $ret->withCell($rowId, 'head')
                        ->setContent($k)
                        ->setHead()
                        ->withAttr('scope', 'row')
                        ;

                    foreach ($labelAttr as $attrName => $attrValue) {
                        $ret->withCell($rowId, 'head')->withAttr($attrName, $attrValue);
                    }

                    if ($countItem > 1) {
                        $ret->withCell($rowId, 'head')->withAttr('rowspan', $countItem);
                    }
                }

                $ret->withCell($rowId, 'content')->setContent($v);

                if (is_string($label)) {
                    if ($j_ > 1) {
                        $attr = $el->getItemAttr($label . ':' . $j_);
                    } else {
                        $attr = $el->getItemAttr($label);
                    }
                    foreach ($attr as $k => $v) {
                        $ret->withCell($rowId, 'content')->withAttr($k, $v);
                    }
                }

                foreach ($valueAttr as $attrName => $attrValue) {
                    $ret->withCell($rowId, 'content')->withAttr($attrName, $attrValue);
                }
            }
        }

        return $ret;
    }
}
