<?php
/**
 * RSS Handler to apply filters to an RSS feed based on requested 'mode'
 *
 * RSS Feed formats can be defined in WP_AUX\Entities\RssFeed with a new entity
 * foreach each format, extending WP_AUX\Entities\RssFeed\RssFeedEntity. The
 * $name property of the format is used to "activate" that format when the "mode"
 * is requested (https://blog.com/post_type/feed/?mode=format)
 */

declare(strict_types=1);

namespace WP_AUX\Entities;

use WP_AUX\Entities\RssFeed\RssFeedEntity;
use WP_AUX\Services\PostService;

class RssHandlerEntity
{
  protected ?RssFeedEntity $activeFeed = null;
  protected array $feeds = [];

  protected function __construct() {
    $tryDirectories = \WP_AUX::tryDirectories(
      \WP_AUX::INCLUDES_DIR .
      '/WP_AUX/Entities/RssFeed'
    );

    foreach ($tryDirectories as $tryDir) {
      $feedFiles = @glob($tryDir . '/*.php');

      foreach ($feedFiles as $feedFile) {
        $feedFileClass = \WP_AUX::fileObjectPath($feedFile);
        $feedName = $feedFileClass::$name;

        if (isset($feeds[$feedName])) {
          continue;
        }

        $this->feeds[$feedName] = $feedFileClass;
      }
    }

    $requestedFeed = $_GET['mode'] ?? RssFeedEntity::$name;

    if (!isset($this->feeds[$requestedFeed])) {
      $requestedFeed = RssFeedEntity::$name;
    }

    if (!empty($requestedFeed) && isset($this->feeds[$requestedFeed])) {
      $this->activeFeed = $this->feeds[$requestedFeed]::create();
    }
  }

  public function itemExcerpt($excerpt): string
  {
    if ($this->activeFeed) {
      $excerpt = $this->activeFeed->itemExcerpt($excerpt);
    }

    return $excerpt;
  }

  public function itemContent($content): string
  {
    if ($this->activeFeed) {
      $content = $this->activeFeed->itemContent($content);
    }

    return $content;
  }

  public function addItemPostType(): void
  {
    $postType = get_post_type();

    if ('post' !== $postType) {
      echo '<category domain="post_type">' . esc_html($postType) . '</category>';
    }
  }

  public function addItemImage(): void
  {
    $post = get_post();

    $mediaContent = '';

    if (has_post_thumbnail($post->ID)) {
      $imageData = PostService::postImageData($post, 'medium', true);

      $attributes = [
        'medium' => 'image',
        'lang' => 'en',
      ];

      $attributesMap = [
        'url' => 'src',
        'fileSize' => 'filesize',
        'type' => 'mime-type',
        'width' => 'width',
        'height' => 'height',
        'alt' => 'alt',
      ];

      foreach ($attributesMap as $mediaAttribute => $imageKey) {
        if (!isset($imageData[$imageKey])) {
          continue;
        }

        $attributes[$mediaAttribute] = $imageData[$imageKey];
      }

      $attributesString = [];
      foreach ($attributes as $attributeName => $attributeValue) {
        $attributesString[] = $attributeName . '="' . esc_attr($attributeValue) . '"';
      }
      $attributesString = join(' ', $attributesString);

      $mediaContent = '<media:content ' . $attributesString . ' />';
    }

    echo $mediaContent;
  }

  public static function prepareHooks(): void
  {
    add_action('rss2_head', function() {
      if (aux_is_browser('safari')) {
        header('Content-Type: text/xml');
      }

      header('X-Content-Type-Options: nosniff');
    });

    add_action('rss2_ns', function() {
      echo 'xmlns:media="http://search.yahoo.com/mrss/"';
    });

    add_action('rss2_item', [self::instance(), 'addItemImage']);
    add_action('rss2_item', [self::instance(), 'addItemPostType']);
    add_filter('the_excerpt_rss', [self::instance(), 'itemExcerpt']);
    add_filter('the_content_feed', [self::instance(), 'itemContent']);
  }

  public static function instance(): static
  {
    static $instance;

    if (is_null($instance)) {
      $instance = new static();
    }

    return $instance;
  }
}
