<?php

namespace Internetgalerie\IgDatapoolFe\Utility;

use TYPO3\CMS\Extbase\Security\Cryptography\HashService;
use TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter;
use Internetgalerie\IgDatapoolFe\Property\TypeConverter\HtmlConverter;
use TYPO3\CMS\Core\SingletonInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;

class MappingUtility implements SingletonInterface
{
    //protected $debug=false;
    //protected $debugLog='/tmp/log2.txt';

    protected $request=null;
    protected $arguments=null;

    /**
     * @var HashService
     */
    protected $hashService = null;

    /**
     * @param HashService $hashService
     */
    public function injectHashService(HashService $hashService): void
    {
        $this->hashService = $hashService;
    }


    public function enableMapping($request, $arguments): void
    {
        $this->request = $request;
        $this->arguments = $arguments;
        foreach ($this->arguments->getArgumentNames() as $paramName) {
            if ($this->arguments->hasArgument($paramName)) {
                /*
                if ($this->debug) {
                    $this->log('TEST['.$paramName.']');
                }
                */
                $this->enableMappingForRte($paramName);
                $this->enableMappingForDbObject($paramName);
                $this->enableMappingForInlineFields($paramName, '__dpInlineFields');
            }
            //$this->enableMappingForFile($paramName, '__dpFile');
        }
    }
    public function enableMappingForRte($name): void
    {
        if ($this->request->hasArgument($name)) {
            $arg = $this->request->getArgument($name);
            if (!empty($arg) && is_array($arg)) {
                $pmc = $this->arguments->getArgument($name)->getPropertyMappingConfiguration();
                foreach ($arg as $argumentName=>$argumentValue) {
                    if (isset($argumentValue['__filter'])) {
                        $filter = $argumentValue['__filter'];
                        if ($filter=='html') {
                            $tc = GeneralUtility::makeInstance(HtmlConverter::class);
                            $pmc->forProperty($argumentName)->setTypeConverter($tc);
                        } else {
                            // do we want and error message here?
                        }
                    }
                }
            }
        }
    }

    /**
     * Dynamically allow __dpObject to have properties (objectstorage, filereference, filereferences)
     */
    public function enableMappingForDbObject($name): void
    {
        if ($this->request->hasArgument($name)) {
            $arg = $this->request->getArgument($name);
            if (is_array($arg) && !empty($arg)) {
                foreach ($arg as $argumentName => $argumentValue) {
                    if (isset($argumentValue['__dpObject'])) {
                        /*
                        if ($this->debug) {
                            $this->log('+ enable mapping for ' . $argumentName .'=' . $argumentValue['__dpObject']);
                        }
                        */
                        $pmc = $this->arguments->getArgument($name)->getPropertyMappingConfiguration();
                        $pmc->allowProperties($argumentName);
                        $pmc->forProperty($argumentName . '.*')->allowAllProperties();
                        $pmc->allowCreationForSubProperty($argumentName . '.*');
                        $pmc->allowModificationForSubProperty($argumentName . '.*');
                    }
                }
            }
        }
    }

    /**
     * Dynamically allow inline properties
     */
    public function enableMappingForInlineFields($name, $internalName): void
    {
        $extbaseAttribute = $this->request->getAttribute('extbase');
        if ($extbaseAttribute->getInternalArgument($internalName) && is_array($extbaseAttribute->getInternalArgument($internalName))) {
            $inlineFields = $extbaseAttribute->getInternalArgument($internalName);
            //var_dump( $this->arguments->getArgument('container' ));
            //echo('name='.$name.'<br />');
            foreach ($inlineFields as $f) {
                $f = $this->hashService->validateAndStripHmac($f);
                $pmc = $this->arguments->getArgument($name)->getPropertyMappingConfiguration();
                $pmc->allowProperties($f);
                $pmc->forProperty($f . '.*')->allowAllProperties();
                $pmc->allowCreationForSubProperty($f . '.*');
                $pmc->allowModificationForSubProperty($f . '.*');
                $pmc->forProperty($f . '.*')->setTypeConverterOption(PersistentObjectConverter::class, PersistentObjectConverter::CONFIGURATION_OVERRIDE_TARGET_TYPE_ALLOWED, true);
                // this is ugly
                for ($i = 0; $i < 100; $i++) {
                    $pmc->forProperty($f . '.' . $i)->allowAllProperties();
                    $pmc->allowCreationForSubProperty($f . '.' . $i);
                    $pmc->allowModificationForSubProperty($f . '.' . $i);
                    $pmc->forProperty($f . '.' . $i)->setTypeConverterOption(PersistentObjectConverter::class, PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED, true);
                    $pmc->forProperty($f . '.' . $i)->setTypeConverterOption(PersistentObjectConverter::class, PersistentObjectConverter::CONFIGURATION_MODIFICATION_ALLOWED, true);
                    // to allow __type in inlinerecords
                    $pmc->forProperty($f . '.' . $i)->setTypeConverterOption(PersistentObjectConverter::class, PersistentObjectConverter::CONFIGURATION_OVERRIDE_TARGET_TYPE_ALLOWED, true);
                }
            }
        }
    }

    /*

    public function log($text)
    {
        $fp = fopen($this->debugLog, 'a');
        fputs($fp, $text ."\n");
        fclose($fp);
    }
    */
}
