<?php
namespace App\Entity;

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

/**
 * Entity for activities
 */
class ActivityEntity
{

    /** @var Array List of valid status for an activity */
    public const VALID_STATUS = [
        StatusEnum::OPEN,
        StatusEnum::IN_PROGRESS,
        StatusEnum::WAITING,
        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 scheduled start date */
    protected $startDate = null;

    /** @var DateTime|NULL The scheduled end date */
    protected $endDate = null;

    /** @var DateTime|NULL The effective start date */
    protected $realStartDate = null;

    /** @var DateTime|NULL The effective end date */
    protected $realEndDate = null;

    /** @var ActorEntity|NULL The actor of the activity */
    protected $actor = 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 activity name
     *
     * @return string
     */
    public function getName(): string
    {
        return $this->name;
    }

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

        return $this;
    }

    /**
     * Get the scheduled start date
     *
     * @return DateTime|NULL
     */
    public function getStartDate(): ?DateTime
    {
        return $this->startDate;
    }

    /**
     * Set a new scheduled start date
     *
     * @param DateTime|NULL $startDate
     * @return self
     */
    public function setStartDate(?DateTime $startDate): self
    {
        $this->startDate = $startDate;

        return $this;
    }

    /**
     * Get the scheduled end date
     *
     * @return DateTime|NULL
     */
    public function getEndDate(): ?DateTime
    {
        return $this->endDate;
    }

    /**
     * Set the new schedules end date
     *
     * @param DateTime|NULL $endDate
     * @return self
     */
    public function setEndDate(?DateTime $endDate): self
    {
        $this->endDate = $endDate;

        return $this;
    }

    /**
     * Get the effectiv start date
     *
     * @return DateTime|NULL
     */
    public function getRealStartDate(): ?DateTime
    {
        return $this->realStartDate;
    }

    /**
     * Set the new effective start date
     *
     * @param DateTime|NULL $realStartDate
     * @return self
     */
    public function setRealStartDate(?DateTime $realStartDate): self
    {
        $this->realStartDate = $realStartDate;

        return $this;
    }

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

    /**
     * Set the new effective end date
     *
     * @param DateTime|NULL $realEndDate
     * @return self
     */
    public function setRealEndDate(?DateTime $realEndDate): self
    {
        $this->realEndDate = $realEndDate;

        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 status of the activity
     *
     * @return string
     * @see StatusEnum
     */
    public function getStatus(): string
    {
        return $this->status;
    }

    /**
     * Set a new status for the activity
     *
     * @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;
    }
}