<?php

namespace Internetgalerie\IgDatapoolFe\ViewHelpers\Form;

use Internetgalerie\IgDatapoolFe\Services\LangService;
use Internetgalerie\IgDatapoolFe\Services\IconService;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder;
use TYPO3\CMS\Core\Page\PageRenderer;

class MultiselectViewHelper extends SelectViewHelper implements FieldInterface
{
    use FormFieldTrait;

    // remove if v12 is dropped
    protected PageRenderer $pageRenderer;

    public function injectPageRenderer(PageRenderer $pageRenderer): void
    {
        $this->pageRenderer = $pageRenderer;
    }

    /**
     * initialize arguments.
     *
     * @return void
     * @api
     */
    public function initializeArguments(): void
    {
        parent::initializeArguments();
        //$this->overrideArgument('options', 'mixed', 'Associative array with internal IDs as key, and the values are displayed in the select box', TRUE);
        $this->registerArgument('sorting', 'boolean', 'enable sorting', false);
        $this->registerArgument('main', 'boolean', 'main entry', false, true);

        // dynamic loading with ajax
        $this -> registerArgument('delay', 'integer', 'delay in ms', false, 250);
        $this -> registerArgument('action', 'string', 'Ajax Action', false, 'ajax');
        $this -> registerArgument('arguments', 'array', 'Ajax Arguments', false, []);
        $this -> registerArgument('controller', 'string', 'Ajax Controller', false, null);
        $this -> registerArgument('pluginName', 'string', 'Ajax PluginName', false, null);
        $this -> registerArgument('extensionName', 'string', 'Ajax ExtensionName', false, null);
        $this -> registerArgument('pageUid', 'string', 'Ajax Page UID', false, 0);
    }

    public function render(): string
    {
        $this->pageRenderer->loadJavaScriptModule('@dp/elements/select-box.js'); 
        $this->arguments['multiple'] = true;
        $options = $this->getOptions();

        ///register token for each field
        //if( $this->arguments['main']) {
        //for ($i = 0; $i < count($options); $i++) {
        $this->registerFieldNameForFormTokenGeneration($this->getName() . '[]');
        //}
        //}


        $pageUid = (int)$this->arguments['pageUid'];
        if ($pageUid == 0) {
            $request = $this->getRequest();
            $pageInformation = $request->getAttribute('frontend.page.information');
            $pageUid = $pageInformation !== null ? $pageInformation->getId() : (int)$GLOBALS['TSFE']->id;
        }

        if ($pageUid && $this->arguments['action'] &&  $this->arguments['controller'] && $this->arguments['extensionName'] && $this->arguments['pluginName']) {
            $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);

            $uriBuilder
                ->reset()
                ->setRequest($this->getRequest())
                ->setTargetPageUid($pageUid);
            $uriBuilder->setCreateAbsoluteUri(true);
            $uri =$uriBuilder->uriFor($this->arguments['action'], $this->arguments['arguments'], $this->arguments['controller'], $this->arguments['extensionName'], $this->arguments['pluginName']);
            $chashPos = strrpos($uri, '&cHash=');
            if ($chashPos>0) {
                $uri = substr($uri, 0, $chashPos);
            }
        } else {
            $uri = null;
        }

        $left = '
<div class="dp-multiSelectLabel"><span class="dp-mutliSelectLabelSpan">' . LangService::ll('field.multiselect.selected') . '</span><br />
<select class="left ' . ($this->hasError() ? $this->arguments['errorClass'] : '') . '" name="left" multiple="multiple" >

	</select>
	</div>';

        $optionsHTML = $this->renderOptionTags($options);
        $filterAttributes = 'placeholder="' . LangService::ll('field.multiselect.filter') . '"';
        $filterAttributes .=  ' style="border-top:1px solid white"';
        $filterAttributes .=  ' class="filter' . ($uri ? ' filter-ajax' : '') . '"';

        if ($this->arguments['delay']) {
            $filterAttributes .= ' data-delay="' . $this->arguments['delay'] . '"';
        }
        if ($uri) {
            $filterAttributes .= ' data-ajax-url="' . $uri . '"';
        }
        $filter = '<input type="text" name="filter" value="" ' . $filterAttributes . ' />';
        $right = '<div class="dp-multiSelectLabel dp-multiSelectLabel-right"><div class="dp-multiSelectLabelTitle"><span class="dp-mutliSelectLabelSpan">' . LangService::ll('field.multiselect.available') . '</span></div><div class="dp-multiSelectSelect">
	<select class="right" name="right" multiple="multiple" >
		' . $optionsHTML . '
	</select></div><div class="dp-multiSelectFilter">' . $filter . '</div>
	</div>';

        //controls
        $middle = '
<div class="center"><span class="dp-mutliSelectLabelSpan">&nbsp;</span><br />
	'.IconService::getIcon('actions-edit-delete', 'dp-delete').'';
        if ($this->arguments['sorting']) {
            $middle .= IconService::getIcon('actions-move-up', 'up').'
	'. IconService::getIcon('actions-move-down', 'down');
        }
        $middle .= '</div>';

        //hidden fields one for emtpy, and other for multipl.e - only on the first element
        if ($this->arguments['main']) {
            $hiddenFields = '<input type="hidden" name="' . $this->getName() . '" value="" />';
            //$hiddenFields = 'W=' . $this->arguments['main'] . '<input type="text" name="' . $this->getName() . '" value="" />';
        }
        /*
        // Wird per JavaScript gemacht ?!
        foreach ($options as $value => $label) {
          if ($this->isSelected($value))
              $hiddenFields .= '<input type="hidden" name="' . $this->getName() . '[]" value="' . htmlspecialchars($value) . '" />';
        }
        */
        $errorClass = '';
        $mappingResultsForProperty = $this->getMappingResultsForProperty();
        if ($mappingResultsForProperty->hasErrors()) {
            if ($this->hasArgument('errorClass')) {
                $errorClass = $this->arguments['errorClass'];
            } else {
                $errorClass = 'error';
            }
        }

        return '<div data-nametemplate="' . $this->getName() . '[]" class="dp-multiSelectBox ' . ($this->arguments['class'] ?? '') . $errorClass . '" id="' . htmlspecialchars((string) ($this->arguments['id'] ?? '')) . '">' . $left . $middle . $right . $hiddenFields . '</div>';
    }

    protected function isSelected($value): bool
    {
        $selectedValue = $this->getSelectedValue();
        if ($value === $selectedValue || (string)$value === $selectedValue) {
            return true;
        }
        if (is_null($selectedValue) && ((is_array($this->arguments['default']) && in_array($value, $this->arguments['default'])) || ($this->arguments['default'] == $value))) {
            return true;
        }
        if (is_null($selectedValue) && $this->arguments['selectAllByDefault'] === true) {
            return true;
        } elseif (is_array($selectedValue) && in_array($value, $selectedValue)) {
            return true;
        }

        return false;
    }


    /**
     * Render the option tags.
     *
     * @param  array $options the options for the form.
     * @return string rendered tags.
     */
    protected function renderOptionTags(array $options): string
    {
        $output = '';
        if ($this->hasArgument('prependOptionLabel')) {
            $value = $this->hasArgument('prependOptionValue') ? $this->arguments['prependOptionValue'] : '';
            $label = $this->arguments['prependOptionLabel'];
            $output .= $this->renderOptionTag($value, $label, false) . chr(10);
        }
        // Zuerst die selektierten Werte geordnet nach sorting
        if ($this->getValueAttribute()) {
            if (empty($options)) {
                foreach ($this->getValueAttribute() as $obj) {
                    //$options[$obj->getUid()] = $obj->__toString();
                    $output .= $this->renderOptionTag($obj->getUid(), $obj->__toString(), true) . chr(10);
                }


                return $output;
            } else {
                foreach ($this->getValueAttribute() as $obj) {
                    foreach ($options as $value => $label) {
                        if (is_object($obj)) {
                            if ($obj->getUid()==$value) {
                                $output .= $this->renderOptionTag($value, $label, true) . chr(10);
                                unset($options[$value]);
                                break;
                            }
                        } elseif (is_string($obj) && $obj != '') {
                            if ($obj==$value) {
                                $output .= $this->renderOptionTag($value, $label, true) . chr(10);
                                unset($options[$value]);
                                break;
                            }
                        }
                    }
                }
            }
        }

        // die restlichen Felder
        foreach ($options as $value => $label) {
            $isSelected = $this->isSelected($value);
            $output .= $this->renderOptionTag($value, $label, $isSelected) . chr(10);
        }
        return $output;
    }
}
