<?php

namespace Webapp\Core\ApiOperation;

use ApiPlatform\Core\Api\IriConverterInterface;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\Security\Core\Security;
use Webapp\Core\Entity\Experiment;
use Webapp\Core\Entity\Individual;
use Webapp\Core\Entity\Move\Edit;
use Webapp\Core\Entity\Platform;
use Webapp\Core\Entity\SurfacicUnitPlot;

/**
 * Class EditBusinessObjectOperation.
 */
final class EditBusinessObjectOperation extends MultipleBusinessObjectAbstractOperation
{

    public function __construct(Security $security, IriConverterInterface $iriConverter, EntityManagerInterface $entityManager)
    {
        parent::__construct($security, $iriConverter, $entityManager);
    }

    /**
     * @param Request $request
     * @param $data Edit
     * @return mixed
     */
    public function __invoke(Request $request, $data)
    {
        /** @var Platform | Experiment $parent common parent to do security checks */
        $parent = null;
        /** @var array<SurfacicUnitPlot | Individual> $objectToMove iri => leaf object */
        $objectToMove = $this->getObjectLeafs($data->getObjectIris(), $parent);

        // TODO Faire les tests de sécurité sur le parent

        // In the case a move is asked
        if ($data->getDx() !== null && $data->getDy() !== null) {
            /** @var array<SurfacicUnitPlot | Individual> $positionMap x,y => leaf object */
            $positionMap = [];
            if ($parent instanceof Platform) {
                $this->handlePlatform($parent, $positionMap, false);
            } else {
                $this->handleExperiment($parent, $positionMap, false);
            }
            foreach ($objectToMove as $item) {
                $item->setX($item->getX() + $data->getDx());
                $item->setY($item->getY() + $data->getDY());
                if (
                    $item->getX() < 1 || $item->getY() < 1 || (
                        isset($positionMap[$item->getX() . ',' . $item->getY()]) &&
                        !isset($objectToMove[$this->iriConverter->getIriFromItem($positionMap[$item->getX() . ',' . $item->getY()])])
                    )
                ) {
                    throw new BadRequestHttpException();
                }
            }
        }

        //In the case a color change is asked
        if ($data->getColor() !== null) {
            foreach ($data->getObjectIris() as $key => $iriTab) {
                foreach ($iriTab as $iri) {
                    $this->iriConverter->getItemFromIri($iri)->setColor($data->getColor());
                }
            }
        }
        $this->entityManager->flush();
        $data->setId(0)->setObjectIris(array_keys($objectToMove));

        return $data;
    }
}
