<?php
declare(strict_types=1);

namespace WP_AUX\Entities\Embeds;

use WHOOP\Entities\Element;
use WHOOP\Entities\Elements\Iframe;
use WHOOP\Entities\Elements\Video;
use WP_AUX\Entities\Embeds\Traits\VideoTraits;

class VideoSourceEntity
{
  use VideoTraits;

  public static bool $isIframe = true;
  public static string $urlPattern = '';
  public static string $embedPattern = '';
  public static string $linkPattern = '';

  public static string $allow = '';
  public static string $allowFullscreen = '';
  public static string $referrerPolicy = '';

  protected string $url = '';
  protected string $id = '';
  protected ?string $title = null;
  protected ?string $mimeType = null;
  protected array $properties = [];

  public function __construct(string $url, ?string $title = null) {
    $this->url = $url;
    $this->title = $title;

    if (static::$urlPattern) {
      $this->id = $this->getIdFromUrl($url);
    }
  }

  public static function getIdFromUrl(string $url): ?string
  {
    if (!static::$urlPattern) {
      return '';
    }

    preg_match(static::$urlPattern, $url, $matches);

    return @$matches[1];
  }

  public function getTitle(): ?string
  {
    return $this->title;
  }

  public function setTitle(?string $title): self
  {
    $this->title = $title;
    return $this;
  }

  public function setId(string $id): self
  {
    $this->id = $id;
    return $this;
  }

  public function setMimeType(?string $mimeType): self
  {
    $this->mimeType = $mimeType;
    return $this;
  }

  public function setProperties(array $properties): self
  {
    $this->properties = $properties;
    return $this;
  }

  public function getProperties(): array
  {
    return $this->properties;
  }

  public function getProperty(string $key): mixed
  {
    return @$this->properties[$key];
  }

  public function embedUrl(): string
  {
    $url = str_replace('{id}', $this->id, static::$embedPattern);

    if ($embedUrlParams = $this->embedUrlParams()) {
      $url .= (substr_count($url, '?') ? '&' : '?') . $embedUrlParams;
    }

    return $url;
  }

  protected function embedUrlParams(): string
  {
    return '';
  }

  public function linkUrl(): string
  {
    return str_replace('{id}', $this->id, static::$linkPattern);
  }

  /**
   * @param Video|Iframe $element
   */
  protected function prepareElement($element): void {}

  /**
   * @return Iframe|null
   */
  public function getElement(): ?Element
  {
    if (empty($this->embedUrl())) {
      return null;
    }

    $attr = [
      'src' => $this->embedUrl(),
      'title' => $this->getTitle(),
      'allow' => $this::$allow,
      'referrerpolicy' => $this::$referrerPolicy,
      'allowfullscreen' => $this::$allowFullscreen,
    ];

    $element = Iframe::create('', $attr);

    $this->prepareElement($element);

    return $element;
  }

  public function __toString(): string
  {
    return (string) $this->getElement();
  }

  public static function create(
    string|array $video,
    ?string $title = null
  ): static
  {
    if (is_array($video)) {
      $url = $video['url'];
      $title = $video['title'];
    } else {
      $url = $video;
    }

    $videoSource = new static($url, $title);

    return $videoSource;
  }
}
