<?php

declare(strict_types=1);

/*
 * Chill is a software for social workers
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Chill\EventBundle\Entity;

use Chill\DocStoreBundle\Entity\StoredObject;
use Chill\MainBundle\Doctrine\Model\TrackCreationInterface;
use Chill\MainBundle\Doctrine\Model\TrackCreationTrait;
use Chill\MainBundle\Doctrine\Model\TrackUpdateInterface;
use Chill\MainBundle\Doctrine\Model\TrackUpdateTrait;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable;
use Chill\MainBundle\Entity\HasCenterInterface;
use Chill\MainBundle\Entity\HasScopeInterface;
use Chill\MainBundle\Entity\Location;
use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Entity\User;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * Class Event.
 */
#[ORM\Entity]
#[ORM\HasLifecycleCallbacks]
#[ORM\Table(name: 'chill_event_event')]
class Event implements HasCenterInterface, HasScopeInterface, TrackCreationInterface, TrackUpdateInterface
{
    use TrackCreationTrait;
    use TrackUpdateTrait;

    #[Assert\NotNull]
    #[ORM\ManyToOne(targetEntity: Center::class)] // A
    private ?Center $center = null;

    #[ORM\ManyToOne(targetEntity: Scope::class)]
    private ?Scope $circle = null;

    #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_MUTABLE)]
    private ?\DateTime $date = null;

    #[ORM\Id]
    #[ORM\Column(name: 'id', type: \Doctrine\DBAL\Types\Types::INTEGER)]
    #[ORM\GeneratedValue(strategy: 'AUTO')]
    private ?int $id = null;

    #[ORM\ManyToOne(targetEntity: User::class)]
    private ?User $moderator = null;

    #[Assert\NotBlank]
    #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 150)]
    private ?string $name = null;

    /**
     * @var Collection<int, Participation>
     */
    #[ORM\OneToMany(mappedBy: 'event', targetEntity: Participation::class)]
    private Collection $participations;

    #[Assert\NotNull]
    #[ORM\ManyToOne(targetEntity: EventType::class)]
    private ?EventType $type = null;

    #[ORM\Embedded(class: CommentEmbeddable::class, columnPrefix: 'comment_')]
    private CommentEmbeddable $comment;

    #[ORM\ManyToOne(targetEntity: Location::class)]
    #[ORM\JoinColumn(nullable: true)]
    private ?Location $location = null;

    /**
     * @var Collection<int, StoredObject>
     */
    #[ORM\ManyToMany(targetEntity: StoredObject::class, cascade: ['persist', 'refresh'])]
    #[ORM\JoinTable('chill_event_event_documents')]
    private Collection $documents;

    #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DECIMAL, precision: 10, scale: 4, nullable: true, options: ['default' => '0.0'])]
    private string $organizationCost = '0.0';

    /**
     * Event constructor.
     */
    public function __construct()
    {
        $this->participations = new ArrayCollection();
        $this->documents = new ArrayCollection();
        $this->comment = new CommentEmbeddable();
    }

    /**
     * Add participation.
     *
     * @return Event
     */
    public function addParticipation(Participation $participation)
    {
        $this->participations[] = $participation;

        return $this;
    }

    public function addDocument(StoredObject $storedObject): self
    {
        if ($this->documents->contains($storedObject)) {
            $this->documents[] = $storedObject;
        }

        return $this;
    }

    public function removeDocument(StoredObject $storedObject): self
    {
        $this->documents->removeElement($storedObject);

        return $this;
    }

    /**
     * @return Center
     */
    public function getCenter(): ?\Chill\MainBundle\Entity\Center
    {
        return $this->center;
    }

    /**
     * @return Scope
     */
    public function getCircle(): ?\Chill\MainBundle\Entity\Scope
    {
        return $this->circle;
    }

    /**
     * Get date.
     *
     * @return \DateTime
     */
    public function getDate(): ?\DateTime
    {
        return $this->date;
    }

    /**
     * Get id.
     *
     * @return int
     */
    public function getId(): ?int
    {
        return $this->id;
    }

    public function getModerator(): ?User
    {
        return $this->moderator;
    }

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

    /**
     * @return Collection<int, Participation>
     */
    public function getParticipations(): Collection
    {
        return new ArrayCollection(iterator_to_array($this->getParticipationsOrdered()));
    }

    /**
     * Sort Collection of Participations.
     */
    public function getParticipationsOrdered(): \ArrayIterator|\Traversable
    {
        $iterator = iterator_to_array($this->participations->getIterator());

        uasort($iterator, static fn ($first, $second) => strnatcasecmp($first->getPerson()->getFirstName(), $second->getPerson()->getFirstName()));

        return new \ArrayIterator($iterator);
    }

    /**
     * @deprecated
     *
     * @return Scope
     */
    public function getScope(): ?\Chill\MainBundle\Entity\Scope
    {
        return $this->getCircle();
    }

    /**
     * @return EventType
     */
    public function getType(): ?\Chill\EventBundle\Entity\EventType
    {
        return $this->type;
    }

    /**
     * Remove participation.
     */
    public function removeParticipation(Participation $participation): void
    {
        $this->participations->removeElement($participation);
    }

    /**
     * @return $this
     */
    public function setCenter(Center $center)
    {
        $this->center = $center;

        return $this;
    }

    /**
     * @return $this
     */
    public function setCircle(Scope $circle)
    {
        $this->circle = $circle;

        return $this;
    }

    /**
     * Set date.
     *
     * @return Event
     */
    public function setDate(\DateTime $date)
    {
        $this->date = $date;

        return $this;
    }

    public function setModerator(User $moderator): self
    {
        $this->moderator = $moderator;

        return $this;
    }

    /**
     * Set label.
     *
     * @return Event
     */
    public function setName(?string $label)
    {
        $this->name = $label;

        return $this;
    }

    /**
     * @return $this
     */
    public function setType(EventType $type)
    {
        $this->type = $type;

        return $this;
    }

    public function getComment(): CommentEmbeddable
    {
        return $this->comment;
    }

    public function setComment(CommentEmbeddable $comment): void
    {
        $this->comment = $comment;
    }

    public function getLocation(): ?Location
    {
        return $this->location;
    }

    public function setLocation(?Location $location): void
    {
        $this->location = $location;
    }

    public function getDocuments(): Collection
    {
        return $this->documents;
    }

    public function setDocuments(Collection $documents): void
    {
        $this->documents = $documents;
    }

    public function getOrganizationCost(): string
    {
        return $this->organizationCost;
    }

    public function setOrganizationCost(string $organizationCost): void
    {
        $this->organizationCost = $organizationCost;
    }
}
