(function ($, document, PP_Checklists) {
  'use strict';

  function getImageCaptionLengths(content) {
    var lengths = [];
    var captions = [];

    if (typeof content !== 'string' || !content.length) {
      return lengths;
    }

    var match;
    var figcaptionRegex = /<figcaption[^>]*>([\s\S]*?)<\/figcaption>/gi;
    while ((match = figcaptionRegex.exec(content)) !== null) {
      captions.push(match[1]);
    }

    var shortcodeRegex = /\[caption[^\]]*\]([\s\S]*?)\[\/caption\]/gi;
    while ((match = shortcodeRegex.exec(content)) !== null) {
      captions.push(match[1].replace(/<img[^>]*>/gi, ''));
    }

    var wpCaptionRegex = /<p[^>]*class=(["'])(?:[^"']*\s)?wp-caption-text(?:\s[^"']*)?\1[^>]*>([\s\S]*?)<\/p>/gi;
    while ((match = wpCaptionRegex.exec(content)) !== null) {
      captions.push(match[2]);
    }

    var wpCaptionDdRegex = /<dd[^>]*class=(["'])(?:[^"']*\s)?wp-caption-dd(?:\s[^"']*)?\1[^>]*>([\s\S]*?)<\/dd>/gi;
    while ((match = wpCaptionDdRegex.exec(content)) !== null) {
      captions.push(match[2]);
    }

    lengths = captions.map(function (caption) {
      return caption.replace(/<[^>]*>/g, '').trim().length;
    });

    var imageMatches = content.match(/<img\s[^>]*>/gi) || [];
    var imageCount = imageMatches.length;

    if (imageCount > lengths.length) {
      lengths = lengths.concat(Array(imageCount - lengths.length).fill(0));
    }

    if (imageCount > 0 && lengths.length > imageCount) {
      lengths = lengths.slice(0, imageCount);
    }

    return lengths;
  }

  $(function () {
    var $imageCaptionCountElements = $('[id^="pp-checklists-req-image_caption_count"]');

    if ($imageCaptionCountElements.length === 0) {
      return;
    }

    if (typeof PP_Checklists.get_image_caption_lengths !== 'function') {
      PP_Checklists.get_image_caption_lengths = getImageCaptionLengths;
    }

    if (PP_Checklists.is_gutenberg_active()) {
      /**
       * For Gutenberg
       */
      let lastSignature = '';

      wp.data.subscribe(function () {
        var content = PP_Checklists.getEditor().getEditedPostAttribute('content');
        if (typeof content === 'undefined') {
          return;
        }

        var captionLengths = PP_Checklists.get_image_caption_lengths(content);
        var signature = captionLengths.join(',');

        if (signature === lastSignature) {
          return;
        }

        $imageCaptionCountElements.each(function () {
          var $element = $(this);
          var requirementId = $element.attr('id').replace('pp-checklists-req-', '');

          var config = (typeof objectL10n_checklist_requirements !== 'undefined' && objectL10n_checklist_requirements.requirements[requirementId])
            ? objectL10n_checklist_requirements.requirements[requirementId]
            : (typeof objectL10n_checklist_requirements !== 'undefined' && objectL10n_checklist_requirements.requirements['image_caption_count'])
              ? objectL10n_checklist_requirements.requirements['image_caption_count']
              : null;

          if (!config || !config.value) {
            return;
          }

          var min = parseInt(config.value[0]);
          var max = parseInt(config.value[1]);

          var isValid = captionLengths.every(function (length) {
            return PP_Checklists.check_valid_quantity(length, min, max);
          });

          if (requirementId === 'image_caption_count' && wp.data.select('core/block-editor')) {
            const blocks = wp.data.select('core/block-editor').getBlocks();
            const imageBlocks = blocks.filter(block => block.name === 'core/image');

            imageBlocks.forEach(block => {
              let captionText = '';
              if (typeof block.attributes.caption === 'string') {
                captionText = block.attributes.caption;
              } else if (block.attributes.caption && typeof block.attributes.caption === 'object') {
                captionText = block.attributes.caption.text || block.attributes.caption.value || '';
              }

              const captionLength = captionText.replace(/<[^>]*>/g, '').trim().length;
              const hasWarning = !PP_Checklists.check_valid_quantity(captionLength, min, max);

              const listViewElement = document.querySelector(
                `.block-editor-list-view-leaf[data-block="${block.clientId}"]`
              );
              if (listViewElement) {
                listViewElement.setAttribute('data-warning', hasWarning);
              }
            });
          }

          $element.trigger(PP_Checklists.EVENT_UPDATE_REQUIREMENT_STATE, isValid);
        });

        lastSignature = signature;
      });
    } else {
      /**
       * For the Classic Editor
       */
      var $content = $('#content');
      var editor;
      var lastSignature = '';
      var debouncedUpdate = _.debounce(update, 200);

      function update() {
        if ($imageCaptionCountElements.length === 0) {
          return;
        }

        var text;
        if (typeof editor === 'undefined' || !editor || editor.isHidden()) {
          text = $content.val();
        } else {
          text = editor.getContent({ format: 'raw' });
        }

        var captionLengths = PP_Checklists.get_image_caption_lengths(text);
        var signature = captionLengths.join(',');

        if (signature === lastSignature) {
          return;
        }

        $imageCaptionCountElements.each(function () {
          var $element = $(this);
          var requirementId = $element.attr('id').replace('pp-checklists-req-', '');

          var config = (typeof objectL10n_checklist_requirements !== 'undefined' && objectL10n_checklist_requirements.requirements[requirementId])
            ? objectL10n_checklist_requirements.requirements[requirementId]
            : (typeof objectL10n_checklist_requirements !== 'undefined' && objectL10n_checklist_requirements.requirements['image_caption_count'])
              ? objectL10n_checklist_requirements.requirements['image_caption_count']
              : null;

          if (!config || !config.value) {
            return;
          }

          var min = parseInt(config.value[0]);
          var max = parseInt(config.value[1]);

          var isValid = captionLengths.every(function (length) {
            return PP_Checklists.check_valid_quantity(length, min, max);
          });

          $element.trigger(PP_Checklists.EVENT_UPDATE_REQUIREMENT_STATE, isValid);
        });

        lastSignature = signature;
      }

      function bindEditorEvents() {
        if (typeof editor === 'undefined' || !editor || editor.id !== 'content') {
          return;
        }

        editor.off('nodechange keyup change input SetContent Paste Undo Redo ExecCommand ObjectResized', debouncedUpdate);
        editor.on('nodechange keyup change input SetContent Paste Undo Redo ExecCommand ObjectResized', debouncedUpdate);
        debouncedUpdate();
      }

      $(document).on(PP_Checklists.EVENT_TINYMCE_LOADED, function (event, tinymce) {
        editor = tinymce.editors['content'];
        if (typeof editor !== 'undefined') {
          if (editor.initialized) {
            bindEditorEvents();
          } else {
            editor.onInit.add(bindEditorEvents);
          }
        }
      });

      $content.on('input keyup change', debouncedUpdate);
      $('#content-html, #content-tmce').on('click', debouncedUpdate);
      $(document).on('wp-body-content-updated', debouncedUpdate);
      debouncedUpdate();
    }
  });
})(jQuery, document, PP_Checklists);
