<?php

namespace Webapp\Core\ApiOperation;

use ApiPlatform\Core\Api\IriConverterInterface;
use DateTime;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Webapp\Core\Entity\BusinessObject;
use Webapp\Core\Entity\Experiment;
use Webapp\Core\Entity\IdentificationCodeUpdate\IdentificationCodeUpdate;
use Webapp\Core\Entity\Individual;
use Webapp\Core\Entity\SurfacicUnitPlot;

/**
 * Class DeleteBusinessObjectOperation.
 */
final class UpdateIdentificationCodesOperation
{
    private IriConverterInterface $iriConverter;

    private EntityManagerInterface $entityManager;

    public function __construct(IriConverterInterface $iriConverter, EntityManagerInterface $entityManager)
    {
        $this->iriConverter = $iriConverter;
        $this->entityManager = $entityManager;
    }

    /**
     * @param Request $request
     * @return mixed
     */
    public function __invoke(Request $request)
    {
        /** @var Experiment $experiment */
        $experiment = $this->iriConverter->getItemFromIri($request->request->get('experiment'));
        $xyMap = $this->getLeafChildren($experiment);
        if ($request->request->getBoolean('importFromFile')) {

            $separator = $request->request->get('csvSeparator');
            $xColumn = $request->request->get('xColumn');
            $yColumn = $request->request->get('yColumn');
            $codeColumn = $request->request->get('codeColumn');
            $handle = fopen($request->files->get('file'), "r");
            if ($handle) {
                // Read the 1st header line
                $headers = explode($separator, fgets($handle));
                $xColIndex = array_search($xColumn, $headers);
                $yColIndex = array_search($yColumn, $headers);
                $codeColIndex = array_search($codeColumn, $headers);
                if ($codeColIndex === false) {
                    throw new BadRequestHttpException("Column not found in CSV");
                }
                while (($line = fgets($handle)) !== false) {
                    $tab = explode($separator, $line);
                    if (isset($xyMap[$tab[$xColIndex] . ',' . $tab[$yColIndex]])) {
                        $xyMap[$tab[$xColIndex] . ',' . $tab[$yColIndex]]->setIdentifier($tab[$codeColIndex]);
                    } else {
                        throw new BadRequestHttpException("Position not found inside the experiment");
                    }

                }
            }
        } else {
            $timestamp = (new DateTime())->getTimestamp();
            foreach ($xyMap as $object) {
                $object->setIdentifier($timestamp++ . '');
            }
        }
        $this->entityManager->flush();
        return (new IdentificationCodeUpdate())->setId(0);
    }

    /**
     * @param BusinessObject $object
     * @return Individual[] | SurfacicUnitPlot[]
     */
    private function getLeafChildren(BusinessObject $object): array
    {
        if ($object instanceof Individual || $object instanceof SurfacicUnitPlot) {
            return [$object->getX() . ',' . $object->getY() => $object];
        } else {
            return array_merge(...array_map(
                    function ($item) {
                        return $this->getLeafChildren($item);
                    },
                    $object->children())
            );
        }
    }

}
