<?php
declare(strict_types=1);
namespace FluidTYPO3\Flux\Form\Conversion;

/*
 * This file is part of the FluidTYPO3/Flux project under GPLv2 or later.
 *
 * For the full copyright and license information, please read the
 * LICENSE.md file that was distributed with this source code.
 */

use FluidTYPO3\Flux\Form;

class FormToFluidTemplateConverter implements FormConverterInterface
{
    const OPTION_TEMPLATE_SOURCE = 'template_source';

    public function convertFormAndGrid(Form $form, ?Form\Container\Grid $grid, array $configuration): string
    {
        $renderingTemplateChunk = $configuration[static::OPTION_TEMPLATE_SOURCE] ?? 'Hello world';

        $template = <<< TEMPLATE
<f:layout />
<f:section name="Configuration">
    <flux:form id="%s">
        <!-- Generated by EXT:flux from runtime configured content type -->
%s
    </flux:form>
    <flux:grid>
        <!-- Generated by EXT:flux from runtime configured content type -->
%s
    </flux:grid>
</f:section>

<f:section name="Main">
%s
</f:section>
TEMPLATE;

        $formFieldsChunk = $this->renderSheetsAndFields($form);
        $gridChunk = $grid !== null ? $this->renderGrid($grid) : '';

        $source = sprintf($template, $form->getId(), $formFieldsChunk, $gridChunk, $renderingTemplateChunk);

        return $source;
    }

    protected function renderSheetsAndFields(Form $form): string
    {
        $rendered = '';
        /** @var Form\Container\Sheet[] $sheets */
        $sheets = $form->getSheets();
        foreach ($sheets as $sheet) {
            $rendered .= sprintf(
                '<flux:form.sheet name="%s" label="%s">' . PHP_EOL,
                $sheet->getName(),
                $sheet->getLabel()
            );
            /** @var Form\FieldInterface[] $fields */
            $fields = $sheet->getFields();
            foreach ($fields as $field) {
                $rendered .= sprintf(
                    '<flux:field.%s name="%s" label="%s"%s />' . PHP_EOL,
                    $this->getViewHelperNameForFieldType($field),
                    $field->getName(),
                    $field->getLabel(),
                    $this->renderAttributes($field)
                );
            }
            $rendered .= '</flux:form.sheet>' . PHP_EOL;
        }
        return $rendered;
    }

    protected function renderGrid(Form\Container\Grid $grid): string
    {
        $rendered = '';
        foreach ($grid->getRows() as $row) {
            $rendered .= '<flux:grid.row>' . PHP_EOL;
            foreach ($row->getColumns() as $column) {
                $rendered .= sprintf(
                    '<flux:grid.column name="%s" label="%s" colPos="%d" />' . PHP_EOL,
                    $column->getName(),
                    $column->getLabel(),
                    $column->getColumnPosition()
                );
            }
            $rendered .= '</flux:grid.row>' . PHP_EOL;
        }
        return $rendered;
    }

    protected function renderAttributes(Form\FieldInterface $field): string
    {
        $attributes = '';
        if (($transform = $field->getTransform()) !== '') {
            $attributes .= sprintf(' transform="%s" ', $transform);
        }
        if (($default = $field->getDefault()) !== '') {
            $attributes .= sprintf(' default="%s" ', is_scalar($default) ? var_export($default, true) : null);
        }
        if (($clearable = $field->getClearable())) {
            $attributes .= sprintf(' clearable="%d" ', (int)$clearable);
        }
        return trim($attributes);
    }

    protected function getViewHelperNameForFieldType(Form\FieldInterface $field): string
    {
        $parts = explode('\\', get_class($field));
        return lcfirst(end($parts));
    }
}
