<?php

namespace NPS\Factory;

use NPS\Repository\ConsultationRepository;
use NPS\DependencyInjection\IExpertSystemBridge;
use NPS\Entity\ConsultationEntity;
use NPS\Model\Consultation;
use NPS\Model\User;
use NPS\Model\KnowledgeBase;
use NPS\Entity\IEntity;
use Doctrine\ORM\EntityManagerInterface;
use NPS\Exception\ExpertSystemCommunicationException;
use NPS\DependencyInjection\IXMLContentParser;


/**
 * Consultation object factory 
 * @author Lukas Korinek
 */
class ConsultationFactory implements IObjectFactory
{
    use TMemorizedFactory;

    /** @var IExpertSystemBridge $es */
    protected $es;

    /** @var KnowledgeBaseFactory $knowledgeBaseFactory */
    protected $knowledgeBaseFactory;

    /** @var UserFactory $userFactory */
    protected $userFactory;

    /** @var IXMLContentParser $parser */
    protected $parser;

    /** @var EntityManagerInterface $em */
    protected $em;

    public function __construct(
        EntityManagerInterface $em, 
        IExpertSystemBridge $es, 
        IXMLContentParser $parser,
        UserFactory $userFactory, 
        KnowledgeBaseFactory $knowledgeBaseFactory)
    {
        $this->em = $em;
        $this->es = $es;
        $this->parser = $parser;
        $this->userFactory = $userFactory;
        $this->knowledgeBaseFactory = $knowledgeBaseFactory;
    }

    /**
     * @inheritdoc
     */
    public function make(IEntity $entity)
    {
        return $this->load($entity, function($entity)
        {
            if(!$entity->getId())
            {
                $this->em->persist($entity);
            }

            $base = $this->knowledgeBaseFactory->make($entity->base);
            $user = $entity->user ? $this->userFactory->make($entity->user) : null;
            return new Consultation($entity, $base, $this->es, $this->parser, $user);            
        });
    }

    
    /**
     * Creates a new consultation and activates it
     * @param KnowledgeBase $base 
     * @param User $user 
     * @return Consultation|null
     */
    public function create(KnowledgeBase $base, User $user = null)
    {
        if(!$this->es->startConsultation($base->getPath()) || !$state = $this->es->saveConsultationState())
        {
            throw new ExpertSystemCommunicationException($this->es->popMessage());
        }
        
        $entity = ConsultationEntity::create([
            'base' => $base->getEntity(),
            'user' => $user ? $user->getEntity() : null,
            'state' => serialize($state),
        ]);

        $consultation = $this->make($entity);
        return $consultation;
    }
}

