<?php

namespace WP_AUX\Services;

use WHOOP\Entities\Elements\A;
use WHOOP\Entities\Elements\P;

/**
 * Utiltity functions for working with HTML
 * @since 1.0.0
 */
class HtmlService
{
  /**
   * Check if a string contains any HTML
   *
   * @todo Support specifying what tags to test for
   * @since 1.0.0
   */
  public static function hasHtml(?string $value): bool
  {
    $value = (string) $value;
    return strip_tags($value) !== $value;
  }

  /**
   * Place a value in the provided sprintf format if that value is not empty.

   * @param string $format sprintf format string to insert provided value into
   * @param mixed ...$additionalValues Any additional data to place in the provided sprintf format if the primary value is not empty
   * @since 1.0.0
   */
  public static function formattedValue($value, string $format = '', ...$additionalValues): string
  {
    if (!$value) {
      return '';
    }

    $values = [ $value ];

    if ($additionalValues) {
      foreach ($additionalValues as $additionalValue) {
        $values[] = $additionalValue;
      }
    }

    // Return the formatted value with a newline to add a space for span and other inline elements
    return !empty($format) ? vsprintf("$format \n", $values) : "$value ";
  }

  /**
   * Put content in a paragraph, if that content isn't already HTML
   * @since 1.0.0
   */
  public static function paragraph(?string $content, ?string $class = null): P|string
  {
    if (self::hasHtml($content)) {
      return (string) $content;
    }

    $paragraph = P::create($content);

    if (!empty($class)) {
      $paragraph->addClass($class);
    }

    return (string) $paragraph;
  }

  /**
   * Add more specific body classes
   * @since 1.0.0
   */
  public static function makeBodyClassy(array $classes): array
  {
    if (is_single()) {
      $post = get_post();

      if ($post) {
        $classes[] = 'single-' . get_post_type() . '--' . $post->post_name;
      }
    }

    $directories = explode('/', trim(str_replace( home_url(), "", get_the_permalink()), '/'));
    $level = max(count($directories) - 1, 0);
    array_pop($directories);

    foreach ($directories as $directory) {
      $classes[] = 'childof-' . $directory;
    }

    $classes[] = 'level-' . $level;

    $classes = array_merge($classes, PageTemplateService::getBodyClasses());

    return $classes;
  }

  /**
   * Add more specific body classes to the body tag
   *
   * @since 1.0.0
   * @uses HtmlService::makeBodyClassy()
   */
  public static function prepareHooks(): void
  {
    add_action('body_class', [ HtmlService::class, 'makeBodyClassy' ]);
  }

  /**
   * Make an anchor link object
   *
   * Attributes for external links are set automatically.
   *
   * @param string|\WHOOP\Entities\Element|null $content Content to display inside the anchor tag
   * @since 1.0.0
   */
  public static function link(
    mixed $content,
    string|array|null $link,
    bool $checkForExternal = true
  ): A
  {
    if (!is_array($link)) {
      $link = [
        'href' => $link,
      ];
    } else {
      if (isset($link['url'])) {
        $link['href'] = $link['url'];
        unset($link['url']);
      }

      // Remove 'title' key from link array to prevent it from becoming a title attribute
      // The 'title' key in ACF link arrays is the link text, not an HTML attribute
      if (isset($link['title'])) {
        unset($link['title']);
      }
    }

    $link = A::create($content, $link);

    /*
     * If the link is external, add the AUX external link class
     */
    if (
      $checkForExternal &&
      parse_url($link->getAttributeValue('href'), PHP_URL_HOST) !== $_SERVER['HTTP_HOST']
    ) {
      $link->addClass('external-link');
    }

    return $link;
  }
}
