<?php

namespace App\Entity;

use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use App\Entity\Trait\UniqueOrderTrait;
use App\Entity\Interface\ICachableImage;
use App\Entity\Trait\TimestampableTrait;
use App\Repository\EventMediaRepository;
use App\Entity\Trait\ForceUpdatableTrait;
use App\Entity\Interface\IUniqueOrderable;
use Doctrine\ORM\Mapping\UniqueConstraint;
use App\Entity\Interface\CachedImageColumn;
use App\Entity\Listener\UniqueOrdreListener;
use App\Entity\Interface\IVideoCachableImage;
use App\Entity\Interface\CachedImageDimensions;
use Symfony\Component\HttpFoundation\File\File;
use App\Entity\Interface\CachedVideoImageColumn;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraints as Assert;

#[ORM\HasLifecycleCallbacks]
#[UniqueEntity(fields: ["event", "ordre", "enabledOrdreUniqueKey"], message: "admin.event-media.fields.@event+ordre.errors.already-existing")]
#[UniqueConstraint(name: "IDX_event_media_event_id_ordre", columns: ["event_id", "ordre", "enabledOrdreUniqueKey"])]
#[ORM\Entity(repositoryClass: EventMediaRepository::class)]
#[ORM\EntityListeners([UniqueOrdreListener::class])]
#[ORM\Table(name: 'event_media')]
#[Vich\Uploadable]
class EventMedia implements IUniqueOrderable, ICachableImage, IVideoCachableImage
{
    use TimestampableTrait;
    use UniqueOrderTrait;
    use ForceUpdatableTrait;

    const t_root = "admin.event-media";
    
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\ManyToOne(inversedBy: 'medias')]
    #[ORM\JoinColumn(name: 'event_id', nullable: false)]
    private ?Event $event = null;

    private ?\DateTime $date = null;

    #[ORM\Column(name: "img_media", length: 255, nullable: true)]
    private ?string $imgMediaFileName = null;

    // NOTE: This is not a mapped field of entity metadata, just a simple property.
    #[Vich\UploadableField(mapping: 'eventmedias', fileNameProperty: 'imgMediaFileName')] //, size: 'logoSize')]
    private ?File $imgMediaFile = null;

    #[Assert\Url(protocols: ['https'], message: self::t_root . ".fields.@video-media.errors.url-invalid")]
    #[ORM\Column(name: "video_media", length: 255, nullable: true)]
    private ?string $videoMedia = null;

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getEvent(): ?Event
    {
        return $this->event;
    }

    public function setEvent(?Event $event): static
    {
        $this->event = $event;

        return $this;
    }

    public function getDate(): ?\DateTime
    {
        return $this->date;
    }

    public function setDate(\DateTime $date): static
    {
        $this->date = $date;

        return $this;
    }

    public function getImgMediaFileName(): ?string
    {
        return $this->imgMediaFileName;
    }

    public function setImgMediaFileName(?string $imgMediaFileName): static
    {
        $this->imgMediaFileName = $imgMediaFileName;

        return $this;
    }
   

    /**
     * If manually uploading a file (i.e. not using Symfony Form) ensure an instance
     * of 'UploadedFile' is injected into this setter to trigger the update. If this
     * bundle's configuration parameter 'inject_on_load' is set to 'true' this setter
     * must be able to accept an instance of 'File' as the bundle will inject one here
     * during Doctrine hydration.
     *
     * @param File|\Symfony\Component\HttpFoundation\File\UploadedFile|null $imageFile
     */
    public function setImgMediaFile(?File $imgMediaFile = null): static
    {
        $this->imgMediaFile = $imgMediaFile;

        if (null !== $imgMediaFile) {
            // It is required that at least one field changes if you are using doctrine
            // otherwise the event listeners won't be called and the file is lost
            $this->updatedAt = new \DateTime();
            // $this->imgMediaCached = [];
        }

        return $this;
    }

    public function getImgMediaFile(): ?File
    {
        return $this->imgMediaFile;
    }
    
    public function getCachedImages() : array {

        $col = new CachedImageColumn();
        $col->field_name = "imgMediaFile";
        $col->filters = [ "galery_media_filter_webp", "galery_media_filter_jpeg", "admin_event_list_filter" ];

        // galery_media_filter_jpeg : fixed / 1300 x 1300
        // galery_media_filter_webp : fixed / 1300 x 1300
        // admin_event_medias_list_filter : fixed / 400 x 400

        $col->max_dimensions = new CachedImageDimensions();
        $col->max_dimensions->min_width = 1300;
        $col->max_dimensions->min_height = 1300;

        return [ "imgMediaFile" => $col ];
    }

    public function getVideoMedia(): ?string
    {
        return $this->videoMedia;
    }

    public function getCachedVideoImages() : array {

        $col = new CachedVideoImageColumn();
        $col->field_name = "videoMedia";
        $col->field_imageFile = "imgMediaFile";
        $col->field_imageFileName = "imgMediaFileName";

        return [ "videoMedia" => $col ];
    }

    public function setVideoMedia(string $video_media): static
    {
        $this->videoMedia = $video_media;

        return $this;
    }

    # gestion de l'ordre

    function getTableName() : string {
        return "event_media";
    }

    function getPartitionByColumns() : array {
        return [[
                    "name" => "event_id",
                    "type" => "int"
                ]];
    }

    public function getRealRoleForUser(User $user): string
    {
        if (in_array("ROLE_ADMIN", $user->getRoles())) return "ROLE_EDITOR";
        return $this->getEvent()->getRealRoleForUser($user);
    }

    #[Assert\Callback]
    public function validate(ExecutionContextInterface $context, $payload)
    {
        if ( !$this->imgMediaFileName && !$this->imgMediaFile && !$this->videoMedia ) {
            $context->buildViolation(self::t_root . ".validate.errors.image-and-video-missing")
                ->addViolation();
        }
    }
}
