<?php
declare(strict_types=1);

namespace WP_AUX\Services\AuxCF;

use WP_AUX\Entities\Admin\AuxComponents\AuxComponentsAuditEntity;
use WP_AUX\Entities\AuxCF\PageFieldGroups\AcfInternalPageGroupEntity;
use WP_AUX\Entities\Embeds\VideoEmbedEntity;
use WP_AUX\Services\GlobalSettingsService;
use WP_AUX\Services\HeadService;

/**
 * Utilities for working with AUX blocks
 * @since 1.0.0
 */
class AuxBlocksService
{
  /**
   * Register scripts and styles for the AUX blocks editor
   *
   * Scripts are only loaded in the admin, and only when a post is being edited
   * or created.
   *
   * @since 1.0.0
   */
  public static function registerAuxEditor(): void
  {
    global $pagenow;
    if (
      $pagenow === 'post-new.php' ||
      (
        ( $pagenow == 'post.php' || get_post_type() == 'post')
        && isset($_GET['action']) && 'edit' === $_GET['action']
      )
    ) {
      // Load css and js only in the Gutenberg editor
      HeadService::enqueueLocalScript('aux-blocks', 'js/aux-blocks.js');
      HeadService::enqueueLocalStyle('aux-blocks-css', 'css/aux-blocks.css');
    }
  }

  /**
   * Register API endpoint for reporting AUX components on the site
   *
   * The endpoint returns a list of components available for the site with critical properties
   * of the AUX environment, WP_AUX version, and of components.
   *
   * @since 1.0.0
   */
  public static function registerComponentsEndpoint(): void
  {
    register_rest_route( 'wpaux/v1', '/components', array(
      'methods' => 'GET',
      'callback' => function() {
        $auxComponentsAudit = new AuxComponentsAuditEntity();

        $response = [
          'wpAuxVersion' => WP_AUX::VERSION,
          'auxVersion' => WP_AUX::AUX_VERSION,
          'components' => [],
        ];

        foreach ($auxComponentsAudit->getAuditComponents() as $componentKey => $auditComponent) {
          $fieldGroup = $auditComponent->fieldGroup;

          $response['components'][$fieldGroup::$key] = [
            'key' => $fieldGroup::$key,
            'title' => $auditComponent->title,
            'docs_url' => \AuxCF\Services\FieldGroupService::documentationUrl($fieldGroup),
            'state' => $auditComponent->state,
            'author' => @$auditComponent->blockConfig['author'],
          ];
        }

        return $response;
      },
      'permission_callback' => '__return_true',
    ) );
  }

  /**
   * Register AUX blocks with Wordpress
   * @since 1.0.0
   */
  public static function registerAuxBlocks(): void
  {
    $fieldGroupsEntities = \WP_AUX::instance()->getActiveFieldGroupsEntities();

    foreach ($fieldGroupsEntities as $fieldGroupsEntity) {
      if ($fieldGroupsEntity::isActive()) {
        $tryDirectories = \WP_AUX::tryDirectories('blocks/' . $fieldGroupsEntity::$key);

        foreach ($tryDirectories as $directory) {
          if (file_exists($directory . '/block.json')) {
            register_block_type($directory);
          }
        }
      }
    }
  }

  /**
   * Register all AUX field groups
   *
   * This method is called by the `acf/include_fields` action, assigned in the `prepareHooks()` method.
   *
   * This `aux/register_field_groups` action runs before page builder post types are
   * added to the standard page builder field group.
   * .
   * The `aux/page_builder_post_types` action allows for adding post types to the
   * standard page builder field group..
   *
   * After post types are registered with the standard page builder field group, AUX component
   * field groups and page builder field groups are registered.
   *
   * @since 1.0.0
   */
  public static function registerAuxGroups(): void
  {
    $wpAux = \WP_AUX::instance();

    do_action('aux/register_field_groups');

    $pageBuilderPostTypes = apply_filters('aux/page_builder_post_types', []);

    if (!empty($pageBuilderPostTypes)) {
      foreach ($pageBuilderPostTypes as $postType) {
        AcfInternalPageGroupEntity::addToPostType($postType);
      }
    }

    if (\WP_AUX::instance()->hasRequirementsMet()) {
      self::registerFieldGroups();
      self::registerPageFieldGroups();
    }
  }

  /**
   * Register AUX component field groups
   * @since 1.0.0
   */
  protected static function registerFieldGroups(): void
  {
    $fieldGroupsEntities = \WP_AUX::instance()->getActiveFieldGroupsEntities();

    foreach ($fieldGroupsEntities as $fieldGroupsEntity) {
      if ($fieldGroupsEntity::isActive()) {
        $fieldGroupsEntity->register();
      }
    }
  }

  /**
   * Register all AUX page builder field groups
   * @since 1.0.0
   */
  protected static function registerPageFieldGroups(): void
  {
    $pageFieldGroupsEntities = \WP_AUX::instance()->getActivePageFieldGroupsEntities();

    foreach ($pageFieldGroupsEntities as $pageFieldGroupsEntity) {
      if ($pageFieldGroupsEntity::isActive()) {
        $pageFieldGroupsEntity->register();
      }
    }
  }

  /**
   * Register all video embed sources in javascript with the admin user interface
   * @since 1.0.0
   */
  public static function registerEmbedVideoSources(): void
  {
    $inlineScript = ['const embedVideoSources = [];'];
    foreach (VideoEmbedEntity::$videoSources as $videoSource) {
      $inlineScript[] = 'embedVideoSources.push(' . $videoSource::$urlPattern . ');';
    }

    wp_add_inline_script('aux-blocks', join("\n", $inlineScript), 'before');
  }

  /**
   * Regsiter actions and filters related to AUX blocks, fields, and field groups
   * @since 1.0.0
   */
  public static function prepareHooks(): void
  {
    add_action('acf/include_fields', [ self::class, 'registerAuxGroups' ]);
    add_action('init', [ GlobalSettingsService::class, 'registerSettingsFields' ]);
    add_action('acf/init', [ GlobalSettingsService::class, 'registerGlobalSettingsPage' ]);
    add_action('init', [ self::class, 'registerAuxBlocks' ]);
    add_action('admin_init', [ self::class, 'registerAuxEditor' ]);
    add_action('rest_api_init', [ self::class, 'registerComponentsEndpoint' ]);
    add_action('admin_init', [ self::class, 'registerEmbedVideoSources' ]);
  }
}
