<?php

namespace Webapp\Core\Validator\Experiment;

use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Webapp\Core\Entity\Experiment;
use Webapp\Core\Enumeration\ExperimentStateEnum;

class ExperimentPatchConstraintValidator extends ConstraintValidator
{
    private EntityManagerInterface $entityManager;

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

    /**
     * @param Experiment $value
     * @param Constraint $constraint
     */
    public function validate($value, Constraint $constraint)
    {

        $originalExperiment = $this->entityManager->getUnitOfWork()->getOriginalEntityData($value);
        if(count($originalExperiment) === 0){
            // POST case
            return;
        }
        $this->entityManager->getUnitOfWork()->computeChangeSet($this->entityManager->getClassMetadata(Experiment::class), $value);
        $changes = $this->entityManager->getUnitOfWork()->getEntityChangeSet($value);

        if(isset($changes['platform']) && $value->getPlatform() !== null){
            if(count($value->getPlatform()->getExperiments()) > 0){
                $this->context->buildViolation("Cannot add an experiment to a non-empty platform")->addViolation();
            }
        }

        if (!isset($originalExperiment['platform'])) {
            if (isset($changes['state'])) {
                $this->context->buildViolation("Cannot change the state on unlinked experiment")->addViolation();
            }
        }

        if ($originalExperiment['state'] === ExperimentStateEnum::NON_UNLOCKABLE) {
            $this->context->buildViolation("The state of the experiment does not allow this kind of modification")->addViolation();
        }

        if ($value->getState() >= ExperimentStateEnum::NON_UNLOCKABLE) {
            $this->context->buildViolation("The state cannot be set to that value")->addViolation();
        }

        if ($originalExperiment['state'] === ExperimentStateEnum::LOCKED) {
            if (count($changes) !== 1 || !isset($changes['state'])) {
                $this->context->buildViolation("The state of the experiment does not allow this kind of modification")->addViolation();
            }
        }
    }
}
