<?php

declare(strict_types=1);

/*
 * This file is a part of the DiscordPHP project.
 *
 * Copyright (c) 2015-2022 David Cole <david.cole1340@gmail.com>
 * Copyright (c) 2020-present Valithor Obsidion <valithor@discordphp.org>
 *
 * This file is subject to the MIT license that is bundled
 * with this source code in the LICENSE.md file.
 */

namespace Discord\Builders\Components;

/**
 * Media gallery components allow you to group images, videos or gifs into a gallery grid.
 *
 * @link https://discord.com/developers/docs/components/reference#media-gallery
 *
 * @since 10.5.0
 *
 * @property int                $type  12 for media gallery component.
 * @property ?int|null          $id    Optional identifier for component.
 * @property MediaGalleryItem[] $items 1 to 10 media gallery items.
 */
class MediaGallery extends Content implements Contracts\ComponentV2
{
    public const USAGE = ['Message'];

    /**
     * Component type.
     *
     * @var int
     */
    protected $type = ComponentObject::TYPE_MEDIA_GALLERY;

    /**
     * Array of media gallery items.
     *
     * @var MediaGalleryItem[]
     */
    protected $items = [];

    /**
     * Creates a new media gallery.
     *
     * @return self
     */
    public static function new(): self
    {
        return new self();
    }

    /**
     * Adds a media item to the gallery.
     *
     * @param MediaGalleryItem|string $item        Media gallery item or URL of the media item.
     * @param string|null             $description Description for the media item (max 1024 characters).
     * @param bool                    $spoiler     Whether the media item is a spoiler.
     *
     * @throws \OverflowException Gallery exceeds 10 items.
     * @throws \LengthException   Description exceeds 1024 characters.
     *
     * @return $this
     */
    public function addItem(MediaGalleryItem|string $item, ?string $description = null, bool $spoiler = false): self
    {
        if (count($this->items) >= 10) {
            throw new \OverflowException('You can only have 10 items per media gallery.');
        }

        if (is_string($item)) {
            $item = MediaGalleryItem::new($item, $description, $spoiler);
        }

        $this->items[] = $item;

        return $this;
    }

    /**
     * Returns all the media items in the gallery.
     *
     * @return MediaGalleryItem[]
     */
    public function getItems(): array
    {
        return $this->items;
    }

    /**
     * @inheritDoc
     */
    public function jsonSerialize(): array
    {
        if (empty($this->items)) {
            throw new \DomainException('MediaGallery must have at least one item.');
        }

        $content = [
            'type' => $this->type,
            'items' => $this->items,
        ];

        if (isset($this->id)) {
            $content['id'] = $this->id;
        }

        return $content;
    }
}
