<?php
namespace App\Entity;

use App\Enum\StatusEnum;
use App\Exception\InvalidEnumKeyException;
use App\Helper\StringGenerationHelper;
use DateTime;

/**
 * Entity for activity task
 */
class TaskEntity
{

    /** @var Array List of valid status for an activity */
    public const VALID_STATUS = [
        StatusEnum::OPEN,
        StatusEnum::IN_PROGRESS,
        StatusEnum::WAITING,
        StatusEnum::PLANIFIED,
        StatusEnum::CANCELED,
        StatusEnum::CLOSED,
    ];

    /** @var string The unique identifier of the entity */
    protected $id = '';

    /** @var string The name of the activity */
    protected $name = '';

    /** @var DateTime|NULL The date when the task is planified */
    protected $planifiedDate = null;

    /** @var DateTime|NULL The date when the task were done */
    protected $executionDate = null;

    /** @var ActorEntity|NULL The actor of the task */
    protected $actor = null;

    /** @var ActivityEntity|NULL The related activity if it is in the context of an activity */
    protected $activity = null;

    /** @var string Status of the activity */
    protected $status = StatusEnum::OPEN;

    /**
     * Get the unique ID the entity
     *
     * @return string
     */
    public function getId(): string
    {
        return $this->id;
    }

    /**
     * Set the ID of the entity
     * <br/> This should not be done after creation
     *
     * @param string $id
     * @return self
     */
    public function setId(string $id): self
    {
        $this->id = $id;

        return $this;
    }

    /**
     * Generate and save a random ID
     *
     * @return string Generated ID
     */
    public function generateId(): string
    {
        // Generate ID
        $id = StringGenerationHelper::generateString(array_merge(range('a', 'z'), range('A', 'Z'), range('0', '9')), 8);

        // Save and return
        $this->setId($id);
        return $id;
    }

    /**
     * Get the task name
     *
     * @return string
     */
    public function getName(): string
    {
        return $this->name;
    }

    /**
     * Set a new name for the task
     *
     * @param string $name
     * @return self
     */
    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }

    /**
     * Get the planified execution date
     *
     * @return DateTime|NULL
     */
    public function getPlanifiedDate(): ?DateTime
    {
        return $this->planifiedDate;
    }

    /**
     * Set the planified execution date
     *
     * @param DateTime $planifiedDate
     * @return self
     */
    public function setPlanifiedDate(?DateTime $planifiedDate): self
    {
        $this->planifiedDate = $planifiedDate;

        return $this;
    }

    /**
     * Get the effective execution date
     *
     * @return DateTime|NULL
     */
    public function getExecutionDate(): ?DateTime
    {
        return $this->executionDate;
    }

    /**
     * Set the effective execution date
     *
     * @param DateTime $executionDate
     * @return self
     */
    public function setExecutionDate(?DateTime $executionDate): self
    {
        $this->executionDate = $executionDate;

        return $this;
    }

    /**
     * Get the related actor
     *
     * @return ActorEntity|NULL
     */
    public function getActor(): ?ActorEntity
    {
        return $this->actor;
    }

    /**
     * Set the new related actor
     *
     * @param ActorEntity|NULL $actor
     * @return self
     */
    public function setActor(?ActorEntity $actor): self
    {
        $this->actor = $actor;

        return $this;
    }

    /**
     * Get the related activity
     *
     * @return ActivityEntity|NULL
     */
    public function getActivity(): ?ActivityEntity
    {
        return $this->activity;
    }

    /**
     * Set the related activity
     *
     * @param ActivityEntity $activity
     * @return self
     */
    public function setActivity(?ActivityEntity $activity): self
    {
        $this->activity = $activity;

        return $this;
    }

    /**
     * Get the status of the task
     *
     * @return string
     * @see StatusEnum
     */
    public function getStatus(): string
    {
        return $this->status;
    }

    /**
     * Set a new status for the task
     *
     * @param string $status
     * @return self
     * @see StatusEnum
     */
    public function setStatus(string $status): self
    {
        if (!in_array($status, $this::VALID_STATUS)) {
            throw new InvalidEnumKeyException();
        }
        $this->status = $status;

        return $this;
    }
}