<?php

namespace App\EntityListener;

use App\Entity\Campaign\Tasklist\Task;
use App\Service\User\Factory;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Security\Core\Security;

final class TaskListener
{
    /**
     * @var MessageBusInterface
     */
    private $messageBus;
    /**
     * @var bool
     */
    private $dirty;
    /**
     * @var ContainerInterface
     */
    private $container;

    private $activity;
    /**
     * @var Security
     */
    private $security;
    /**
     * @var Factory
     */
    private $userFactory;

    public function __construct(MessageBusInterface $messageBus, Security $security, ContainerInterface $container)
    {
        $this->messageBus = $messageBus;
        $this->container = $container;
        $this->security = $security;
    }

    /**
     * @ORM\PostPersist()
     *
     * @param Task $task
     */
    public function createFirstVersion(Task $task)
    {
        $userFactory = $this->container->get('App\Service\User\Factory');
        $activity = (new Task\Activity())
            ->setTask($task)
            ->setType('create')
            ->setTitle('created this task');

        if ($this->security->getUser()) {
            $activity->setCreatedBy($this->security->getUser());
        } else {
            $activity->setCreatedBy($userFactory->systemUser());
        }

        $activityService = $this->container->get('App\Service\Campaign\Tasklist\Task\ActivityService');
        $activityService->save($activity);
    }

    /**
     * @ORM\PreUpdate()
     *
     * @param Task               $task
     * @param PreUpdateEventArgs $args
     */
    public function preUpdate(Task $task, PreUpdateEventArgs $args)
    {
        $changeSet = $args->getEntityChangeSet();

        if (array_key_exists('completed', $changeSet)
            || array_key_exists('priority', $changeSet)
            || array_key_exists('title', $changeSet)
            || array_key_exists('description', $changeSet)
            || array_key_exists('user', $changeSet)
            || array_key_exists('dueAt', $changeSet)
        ) {
            $activity = (new Task\Activity())->setCreatedBy($this->security->getUser())->setTask($task);

            if (array_key_exists('completed', $changeSet)) {
                if (1 == $changeSet['completed'][1]) {
                    $activity->setType('complete')
                        ->setTitle('marked this task as done');
                } elseif (0 == $changeSet['completed'][1]) {
                    $activity->setType('uncomplete')
                        ->setTitle('marked this task as not done');
                }
            }

            if (array_key_exists('priority', $changeSet)) {
                $activity->setType('priority')
                    ->setTitle(sprintf('changed priority of this task to %s', $changeSet['priority'][1]));
            }

            if (array_key_exists('title', $changeSet)) {
                $activity->setType('title')
                    ->setTitle(sprintf('changed title to %s', $changeSet['title'][1]));
            }

            if (array_key_exists('description', $changeSet)) {
                $activity->setType('description')
                    ->setTitle(sprintf('changed description of this task'));
            }

            if (array_key_exists('user', $changeSet)) {
                if (null === $changeSet['user'][1]) {
                    $activity->setType('unassign')
                        ->setTitle(sprintf('removed user assignment from this task'));
                } else {
                    $activity->setType('assign')
                        ->setTitle(sprintf('assigned this task to %s %s', $task->getUser()->getFirstName(),
                            $task->getUser()->getLastName()));
                }
            }

            if (array_key_exists('dueAt', $changeSet)) {
                if (null === $changeSet['dueAt'][1]) {
                    $activity->setType('due')
                        ->setTitle(sprintf('removed due date from this task'));
                } else {
                    $activity->setType('due')
                        ->setTitle(sprintf('set due date for this task to %s', $task->getDueAt()->format('d-m-Y')));
                }
            }

            $this->activity = $activity;
            $this->dirty = true;
        }
    }

    /**
     * @ORM\PostUpdate()
     *
     * @param Task $task
     */
    public function updateActivity(Task $task)
    {
        if ($this->dirty) {
            $activityService = $this->container->get('App\Service\Campaign\Tasklist\Task\ActivityService');
            $activityService->save($this->activity);
        }
    }
}
