<?php

namespace Internetgalerie\IgDatapoolFe\ViewHelpers\Form\Select;

use Internetgalerie\IgDatapoolFe\ViewHelpers\Form\Select2ViewHelper;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder;
use TYPO3\CMS\Extbase\Persistence\ObjectStorage;

class AjaxViewHelper extends Select2ViewHelper
{
    protected static $class = 'dp-select-ajax';
    protected static $style = 'width: 100%;';
    
    public function initializeArguments(): void
    {
        parent::initializeArguments();
        $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);
        $this->registerArgument('argumentNameUid', 'string', 'argument name for initial ajax call for uid', false);
        //$this->registerArgument('placeholder', 'string', 'placeholder String', false, '');
        // set default to true
        $this->overrideArgument('allowClear', 'boolean', 'display c clear button ("x" icon) to appear on the select box when a value is selected.', false, true);
    }


    public function render(): string
    {
        
        $this->createPageRendererForSelect2();
        $pageUid = (int)$this->arguments['pageUid'];
        if ($pageUid == 0) {
            $request = $this->renderingContext->getRequest();
            $pageUid = $request->getAttribute('frontend.page.information')->getId();
        }

        $functionName='initSelectAjax' . $this->getIdJs();
        $this->tag->addAttribute('data-dp-init', $functionName);
        $output = parent::render();

        $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
        
        $uriBuilder
            ->reset()
            ->setRequest($this->renderingContext->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);
        }

        $initalUri = '';
        if ($this->arguments['argumentNameUid'] ?? false) {
            $value = $this->getValueAttribute();
            if ($value) {
                $uriBuilder->setArguments(
                    [$this->arguments['argumentNameUid'] => $value]
                );
                $initalUri = $uriBuilder->uriFor($this->arguments['action'], null, $this->arguments['controller'], $this->arguments['extensionName'], $this->arguments['pluginName']);
            }
        }

        if ($this->hasArgument('placeholder')) {
            $placeholder="\nplaceholder: " . json_encode($this->arguments['placeholder']).",";
        } else {
            $placeholder='';
        }
        // prependOptionLabel ?
        if ($this->hasArgument('placeholder')) {
            $allowClear='  allowClear: '. ($this->arguments['allowClear'] ? 'true': 'false') . ',
';
        } else {
            $allowClear='';
        }
        if ($initalUri) {
            $jsSetDefaultValue = "
fetch('" . $initalUri . "')
  .then(response => {
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    return response.json();
  })
  .then(data => {
    // Check if an option with the same value already exists and remove
    var existingOption = el.querySelector('option[value=\"' + data.value + '\"]');
    if (existingOption) {
      existingOption.remove();
    }
    var option = document.createElement('option');
    option.value = data.value;
    option.text = data.label;
    option.selected = true;
    el.appendChild(option);
  })
  .catch(error => {
    console.error('Fetch failed:', error);
  });";
        } else {
            $jsSetDefaultValue = '';
        }


        $js='var '.$functionName . ' = function(el) {
jQuery(el).select2({'.$placeholder.'
'.$allowClear.'  ajax: {
    url: '.json_encode($uri).',
    dataType: "json",
    delay: '.intval($this->arguments['delay']).',
    cache: true
  }
});
' . $jsSetDefaultValue . '
};';

        $this->pageRenderer->addJsFooterInlineCode('.ig-database-fe-' . $this->getId(), $js);

        return $output;
    }

    protected function getOptions(): array
    {
        if ($this->getPropertyValue()) {
            $propertyValue = $this->getPropertyValue();
            if ($propertyValue instanceof ObjectStorage) {
                $options = [];
                foreach ($propertyValue as $subValue) {
                    $options[$subValue->getUid()] = $subValue->__toString();
                }
                return $options;
            }
            return [ $this->getValueAttribute() => $this->getPropertyValue() ];
        }
        $value = $this->arguments['value'];
        if ($value) {
            if (is_object($value)) {
                return [ $this->getValueAttribute() => $value];
                //return [ $this->getValueAttribute() => $value->__toString()];
            }
            return [ $this->getValueAttribute() => $value];
        }
        return [];
    }

    /**
     * get identifier for non extbase objects with getUid method
     */
    protected function getValueAttribute($convertObjects = true)
    {
        $valueAttribute = parent::getValueAttribute($convertObjects);
        return is_object($valueAttribute) && method_exists($valueAttribute, 'getUid') ? $valueAttribute->getUid() : $valueAttribute;
    }
    protected function getId()
    {
        return  $this->arguments['property'];
    }
    protected function getIdJs()
    {
        return str_replace('-', '', $this->getId());
    }

    protected function convertToPlainValue($value)
    {
        if ($value instanceof ObjectStorage) {
            $ret = [];
            foreach ($value as $subValue) {
                $identifier = $this->persistenceManager->getIdentifierByObject($subValue);
                if ($identifier !== null) {
                    $ret[] = $identifier;
                }
            }
            return $ret;
        } else {
            return parent::convertToPlainValue($value);
        }
    }
}
