<?php
declare(strict_types=1);

namespace WP_AUX\Entities\Embeds;

use WP_AUX\Entities\Embeds\VideoSource\HtmlVideoSourceEntity;
use WP_AUX\Entities\Embeds\VideoSource\InternalVideoSourceEntity;
use WP_AUX\Entities\Embeds\VideoSource\VimeoVideoSourceEntity;
use WP_AUX\Entities\Embeds\VideoSource\YoutubeVideoSourceEntity;

class VideoEmbedEntity
{
  /**
   * @var VideoSourceEntity[]
   */
  public static array $videoSources = [
    YoutubeVideoSourceEntity::class,
    VimeoVideoSourceEntity::class,
  ];

  protected ?VideoSourceEntity $videoSource = null;
  protected ?string $layout = null;
  protected ?int $width = null;
  protected ?int $height = null;
  protected array $iframeAttributes = [];

  protected function __construct(VideoSourceEntity $src, array $iframeAttributes = []) {
    $this->videoSource = $src;
    $this->iframeAttributes = $iframeAttributes;
  }

  public function setSourceFeaturesFromArray(?array $features): void
  {
    $autoplay = in_array('autoplay', $features);
    $loop = in_array('loop', $features);
    $muted = in_array('muted', $features);
    $disableControls = in_array('disable_controls', $features);

    if (isset($autoplay)) {
      $this->videoSource->setAutoplay( filter_var($autoplay, FILTER_VALIDATE_BOOLEAN) );
    }

    if (isset($muted)) {
      $this->videoSource->setMuted( filter_var($muted, FILTER_VALIDATE_BOOLEAN) );
    }

    if (isset($loop)) {
      $this->videoSource->setLoop( filter_var($loop, FILTER_VALIDATE_BOOLEAN) );
    }

    if (isset($disableControls)) {
      $this->videoSource->setDisableControls( filter_var($disableControls, FILTER_VALIDATE_BOOLEAN) );
    }
  }

  public function setupEmbedFromArray(array $video): void
  {
    if (isset($video['features'])) {
      $this->setSourceFeaturesFromArray((array) $video['features']);
    }

    $width = (int) $this->videoSource->getProperty('width');
    $height = (int) $this->videoSource->getProperty('height');

    if ($width && $height) {
      $this->width = $width;
      $this->height = $height;
    } elseif (!empty($video['width']) && !empty($video['height'])) {
      $this->width = (int) $video['width'];
      $this->height = (int) $video['height'];
    }

    if (!empty($video['layout'])) {
      $this->layout = $video['layout'];
    } else {
      if (!empty($this->width) && !empty($this->height)) {
        $this->layout = 'custom';
      } else {
        $this->layout = 'horizontal';
      }
    }

    if (empty($this->width) && empty($this->height)) {
      switch ($this->layout) {
        case 'horizontal':
          $this->width = 1600;
          $this->height = 900;
          break;
        case 'vertical':
          $this->width = 900;
          $this->height = 1600;
          break;
        case 'square':
          $this->width = 1600;
          $this->height = 1600;
          break;
      }
    }
  }

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

  public function getShareUrl(): ?string
  {
    return $this->videoSource->linkUrl();
  }

  public function __toString(): string
  {
    $element = $this->videoSource->getElement();

    if (empty($element)) {
      return '';
    }

    if ($this->videoSource::$isIframe && !empty($this->iframeAttributes)) {
      foreach ($this->iframeAttributes as $attributeName => $attributeValue) {
        if (!$element->getAttributeValue($attributeName)) {
          $element->setAttribute($attributeName, $attributeValue);
        }
      }
    }

    if (!empty($this->width) && !empty($this->height)) {
      $element->setDataValue('aspect-ratio', round($this->width/$this->height, 2));
    }

    $element->setDataValue('layout', $this->layout);

    if (!$element->getAttributeValue('width') && !$element->getAttributeValue('height')) {
      if (!empty($this->width)) {
        $element->setAttribute('width', $this->width);
      }

      if (!empty($this->height)) {
        $element->setAttribute('height', $this->height);
      }
    }

    return (string) $element;
  }

  public static function create(string|array $video, array $iframeAttributes = []): ?VideoEmbedEntity
  {
    $videoSourceEntity = false;
    $url = null;
    $file = null;

    if (is_array($video)) {
      if (!empty($video['file'])) {
        $file = $video['file'];
      } else {
        $url = $video['url'];
      }
    } else {
      $url = $video;
    }

    if ($url) {
      foreach (static::$videoSources as $videoSource) {
        if ($videoSource::getIdFromUrl($url)) {
          $videoSourceEntity = $videoSource::create($video);
          break;
        }
      }
    }

    if (!$videoSourceEntity) {
      if (!empty($file)) {
        $videoSourceEntity = InternalVideoSourceEntity::create($video);
      } else {
        $videoSourceEntity = HtmlVideoSourceEntity::create($video ?? $url);
      }
    }

    $videoEmbed = new static($videoSourceEntity, $iframeAttributes);

    if (is_array($video)) {
      $videoEmbed->setupEmbedFromArray($video);
    }

    return $videoEmbed;
  }
}
