/**
 * AUX Blocks Gutenberg Editor JavaScript
 *
 * Enhance the Gutenberg block editor with AUX-specific functionality:
 * - Add visual labels to AUX component blocks showing their component title
 * - Dynamically watch for new blocks and apply labels as blocks are added
 * - Conditionally show/hide video field options based on video URL embed source
 *
 * Only loaded in the Gutenberg editor when editing or creating posts.
 *
 * Enqueued by: inc/WP_AUX/Services/AuxCF/AuxBlocksService.php
 *              (AuxBlocksService::registerAuxEditor() method via admin_init action hook)
 *
 * @since 1.0.0
 */

/**
 * Add AUX component title as a visual label above the block element
 *
 * Check if the block is an AUX component (block type starts with 'aux/') and
 * prepend a label wrapper containing the component title to help identify
 * AUX blocks in the editor. Only add the label once per block.
 *
 * @param {string} blockId - The client ID of the block element
 * @return {boolean} Return false if element not found, already has label, or is not an AUX block
 */
const addAuxTag = (blockId) => {
  let element = document.getElementById('block-' + blockId);

  // Exit if block element doesn't exist
  if (!element) {
    return false;
  }

  // Exit if label has already been added to this block
  let hasLabel = element.dataset.hasLabel;
  if (hasLabel) {
    return false;
  }

  // Check if block type starts with 'aux' (e.g., 'aux/component-name')
  let blockType = element.dataset.type.split('/');

  if ('aux' === blockType[0]) {
    let blockTitle = element.dataset.title;

    // Create label element with component title
    let label = document.createElement("label");
        label.classList.add('aux-block-label');
        label.append(blockTitle);

    // Create wrapper div for the label
    let labelWrapper = document.createElement("div");
        labelWrapper.classList.add('aux-block-label-wrapper');
        labelWrapper.append(label);

    // Prepend label wrapper to the block element
    let wrapper = element;
        wrapper.prepend(labelWrapper);

    // Mark block as having a label to prevent duplicate labels
    element.dataset.hasLabel = true;
  }
};

/**
 * Retrieve the current list of blocks from the Gutenberg editor
 *
 * Use WordPress's block editor data store to get all blocks currently
 * in the editor.
 *
 * @return {Array|undefined} Array of block objects or undefined if block editor not available
 */
const getBlockList = () => {
  let blockEditor = wp.data.select( 'core/block-editor' );

  if (blockEditor) {
    return blockEditor.getBlocks();
  }
};

// Get initial block list when script loads
let blockList = getBlockList();

/**
 * Watch for changes to the block list and add AUX labels to new blocks
 *
 * Subscribe to the WordPress block editor data store to detect when blocks
 * are added, removed, or modified. When changes are detected, iterate through
 * all blocks and add AUX component labels where applicable. Use a small delay
 * to ensure DOM elements are fully rendered before attempting to add labels.
 */
wp.data.subscribe(() => {
  const newBlockList = getBlockList();
  const blockListChanged = newBlockList !== blockList;
  blockList = newBlockList;

  // Only process if block list actually changed
  if ( blockListChanged ) {
    // Small delay to ensure DOM is ready after block changes
    setTimeout(() => {
      blockList.forEach((block) => {
        addAuxTag(block.clientId);
      });
    }, 125);
  }
});

/**
 * Toggle visibility of video option fields based on video URL source
 *
 * If the video URL matches a known embed source pattern (e.g., YouTube, Vimeo),
 * hide additional video configuration fields (alt URL, layout, width, height)
 * since these are not needed for embedded videos. Show these fields for direct
 * video file URLs that require manual configuration.
 *
 * @param {Object} parent - ACF field group parent object containing the video fields
 */
let toggleVideoOptionsFields = function(parent) {
  let urlField = parent.getField('field_video_url');

  // Check if URL matches any embed video source pattern
  // embedVideoSources is defined in PHP via AuxBlocksService::registerEmbedVideoSources()
  let doHide = embedVideoSources.some((regex) =>  urlField.getValue().match(regex) !== null);

  // Fields to hide/show based on video source type
  let hideFields = [
    'field_video_alt_url',
    'field_video_layout',
    'field_video_width',
    'field_video_height',
  ];

  // Toggle visibility of each field
  hideFields.forEach((fieldKey) => {
    let hideField = parent.getField(fieldKey);
    if (doHide) {
      // Hide fields for embed sources (handled automatically by embed)
      hideField.hide( true );
    } else {
      // Show fields for direct video files (require manual configuration)
      hideField.show( true );
    }
  });
};

/**
 * Initialize video URL field behavior when ACF fields are loaded
 *
 * Use ACF's action hook to detect when a video_url field is added to the editor.
 * Set up change event listener to dynamically show/hide related video option fields
 * based on whether the URL is an embed source or direct file.
 */
(function($){
  acf.addAction('new_field/name=video_url', function(field) {
    let parent = field.parent();

    // Set initial field visibility state
    toggleVideoOptionsFields(parent);

    // Update field visibility whenever video URL changes
    field.on('change', (e) => toggleVideoOptionsFields(parent));
  });
})(jQuery);
