import { computePosition, offset, shift, flip } from '@floating-ui/dom';
import allowedBlocks from "./component/compatibility/allowedBlocks"; 
import Board from "../comment/board";

const { __, sprintf } = wp.i18n;
const { createRoot } = wp.element; // eslint-disable-line
const { dispatch, select } = wp.data;
const { isKeyboardEvent } = wp.keycodes;
const { Notice } = wp.components;
const $ = jQuery;

let container = null;

export const createFloatingIcons = (focusedElement) => {
  var mainfloatingparentNode = document.createElement("div");
  mainfloatingparentNode.setAttribute("class", "cf-floating-wrapper-main");
  var floatingparentNode = document.createElement("div");
  floatingparentNode.setAttribute("class", "cf-floating-wrapper");
  var floatingNode = document.createElement("div");
  floatingNode.setAttribute("class", "cf-floating-wrapper__btn");
  var floatinglistNode = document.createElement("ul");
  var commentList = document.createElement("li");
  var suggestionList = document.createElement("li");

  var childcommentList = document.createElement("div");
  childcommentList.setAttribute("class", "cf-admin-comments-holder");
  if (true === wp.data.select("mdstore").getSuggestionMode()) {
    suggestionList.setAttribute("class", "cf-suggestion-active");
  }
  var tooltipList = document.createElement("span");
  tooltipList.setAttribute("class", "tooltip");
  childcommentList.appendChild(tooltipList).append(__("Add Comment", "commenting-feature")); //phpcs:ignore
  commentList.appendChild(childcommentList);

  var html = getSelectionHtml(); // Check if selected text has comment or not. @author: Rishi Shah
  if (null !== html.match(/mdspan/g)) {
    commentList.setAttribute("already_commented", "true");
  } else {
    commentList.setAttribute("already_commented", "false");
  }

  commentList.addEventListener("click", function () {
    const alreadyCommented = commentList.getAttribute('already_commented');
    if('true' === alreadyCommented){
      showNotice(__("Multiple comments are not possible on the same block.", "commenting-feature"));
      $(".cf-floating-wrapper").remove();
      return;
    }
    var block = wp.data.select("core/block-editor").getSelectedBlock();
    if (
      "figure" === focusedElement ||
      "video" === focusedElement ||
      "img" === focusedElement ||
      !allowedBlocks.text.includes(block?.name)
    ) {
      if ("figcaption" === focusedElement) {
        $(".toolbar-button-with-text.comment-group-button").trigger("click");
      } else {
        $(".toolbar-button-with-nontext").trigger("click");
      }
    } else {
      $(".toolbar-button-with-text.comment-group-button").trigger("click");
    }

    $(commentList).addClass("float-active");
    $(".cf-floating-wrapper").remove();
  });

  // $(commentList).removeClass('float-active');

    floatinglistNode.appendChild(commentList);
  

  const referenceNode = document.querySelector(".edit-post-visual-editor");

  if(referenceNode){
    floatingNode.appendChild(floatinglistNode);
    floatingparentNode.appendChild(floatingNode);
    mainfloatingparentNode.appendChild(floatingparentNode);
    referenceNode.appendChild(mainfloatingparentNode);
  }
}

export const updateAutodraftIds = (allThreads) => {
  var data, removedItem;
  var threadsId = [];
  var autodraftIds = [];
  const CurrentPostID = wp.data.select("core/editor").getCurrentPostId(); // eslint-disable-line
  if (!CurrentPostID) {
    console.error('Post ID or Post Type is not defined');
    return;
  }

  // Use WordPress global wp.apiFetch (from wp-api-fetch handle) so REST nonce + middleware match admin; bundled axios/import lacked credentials → 401.
  if (typeof wp === 'undefined' || typeof wp.apiFetch !== 'function') {
    console.error('Multicollab: wp.apiFetch unavailable (enqueue wp-api-fetch).');
    return;
  }
  wp.apiFetch({
    path: `/multicollab/v2/activities?postID=${ encodeURIComponent( CurrentPostID ) }`,
  })
    .then((res) => {
      const threadsPayload = res && res.threads ? res.threads : [];
      data = threadsPayload;
      data.map((th) => {
        if (th.resolved === "false") {
          threadsId.push(th.elID);
        }
      });
      var newThreadsIdSet = new Set(allThreads);
      var setDifference = [...threadsId].filter((x) => !newThreadsIdSet.has(x));
      setDifference.map((ids) => {
        ids = ids.replace("sg", "");
        autodraftIds.push(["th_", ids].join(""));
      });

      var data = {
        action: "multicollab_update_meta",
        currentPostID: CurrentPostID,
        data: autodraftIds,
      };
      $.post(ajaxurl, data, function () {
        // eslint-disable-line
      });
    })
    .catch((err) => {
      console.error('Multicollab: activities REST request failed (autodraft sync skipped).', err);
    });
}


export const removeBlankPopup = (selectedText) => {
  if (
    1 === $(".board.fresh-board").length &&
    0 === $(".board.fresh-board .loading").length
  ) {

    const latestBoard = $(".board.fresh-board")
      .parents(".cls-board-outer")
      .attr("id");
    if (selectedText !== latestBoard) {
      let blockType = $('[datatext="' + latestBoard + '"]').attr("data-type");
      let blockId = $('[datatext="' + latestBoard + '"]').attr("data-block");

      if (!allowedBlocks.text.includes(blockType) && undefined !== blockType) {
        $('[datatext="' + latestBoard + '"]').removeClass("commentIcon ");
        wp.data.dispatch("core/block-editor").updateBlock(blockId, {
          attributes: {
            datatext: "",
          },
        });
      } else {
        removeTag(latestBoard); // eslint-disable-line

        // To resolve whole comment blank popup issue. It will prevent a block from being removed.  @author: - Mayank / since 3.5
        if (
          $('[datatext="' + latestBoard + '"]').hasClass(
            "cf-onwhole-block__comment"
          )
        ) {
          const blockClientID =
            $('[datatext="' + latestBoard + '"]').attr("data-block") || "";
          if (blockClientID) {
            const attributes =
              wp.data
                .select("core/block-editor")
                .getBlockAttributes(blockClientID) || "";
            if (attributes?.className) {
              // Resolved block crash issue #403 @author - Mayank / since 3.5
              attributes.className = attributes?.className?.replace(
                /(cf-onwhole-block__comment)\s*/g,
                ""
              );
              wp.data
                .dispatch("core/block-editor")
                .updateBlockAttributes(blockClientID, {
                  className: attributes.className,
                  datatext: "",
                });
            } else {
              // Resolved block crash issue #403 @author - Mayank / since 3.5
              wp.data
                .dispatch("core/block-editor")
                .updateBlockAttributes(blockClientID, { datatext: "" });
            }
          }

          $('[datatext="' + latestBoard + '"].cf-onwhole-block__comment')
            .removeAttr("datatext")
            .removeClass("cf-onwhole-block__comment");
          $(
            '[datatext="' + latestBoard + '"].cf-icon-wholeblock__comment'
          ).remove();
        } else {
          $('[datatext="' + latestBoard + '"]').remove();
        }
      }

      $("#" + latestBoard).remove();
      //Remove :visible
      $("#history-toggle").attr("data-count", $(".cls-board-outer").length);
      jQuery.event.trigger({ type: "editorLayoutUpdate" });
    }
  }
}

export const removeDataText = (selectedText) => {
  var findMdSpan = ".cls-board-outer";
  var openBoards = $(".cls-board-outer").length;
  let blockType = $('[datatext="' + selectedText + '"]').attr("data-type");
  let blockId = $('[datatext="' + selectedText + '"]').attr("data-block");
  let boardDataArray = [];
  if (0 === openBoards && undefined === blockType) {
    removeTag(selectedText); // eslint-disable-line
  }
  $(findMdSpan).each(function () {
    var boardDatatext = $(this).attr("id");
    boardDataArray.push(boardDatatext);
  });
  if (!boardDataArray.includes(selectedText)) {
    if (undefined !== blockType) {
      $('[datatext="' + selectedText + '"]').removeClass(
        "cf-onwhole-block__comment "
      );
      $('[datatext="' + selectedText + '"]').removeClass(
        "cf-icon-wholeblock__comment "
      );
      $(
        '[datatext="' + selectedText + '"].cf-icon-wholeblock__comment'
      ).remove(); // Resolved #535 for whole comment block @author - Mayank / since 3.6
      wp.data.dispatch("core/block-editor").updateBlock(blockId, {
        attributes: {
          datatext: "",
        },
      });
    } else {
      removeTag(selectedText); // eslint-disable-line
      $('[datatext="' + selectedText + '"]').remove();
    }
    unsetBoardIdByValue(selectedText);
    const boardIdLength = wp.data.select('mdstore').getBoardIds()?.length;
    if(boardIdLength == 0){
       const sidebarName = wp.data.select('core/edit-post').getActiveGeneralSidebarName();
        if (sidebarName === 'edit-post/cf-collab-sidebar') {
            wp.data.dispatch('core/edit-post').closeGeneralSidebar();
        }
    }
  }
}

export const suggestionApply = () => {
  if (false === wp.data.select("mdstore").getSuggestionMode()) {
    const isRealTime = wp.data
      .select("core/editor")
      .getEditedPostAttribute("meta")?._is_real_time_mode;
    if (isRealTime) {
      //if suggestions gets enabled while real-time are enabled
      if (
        confirm(
          __(
            "Real-time Editing will get disable if you enable Suggest Edits",
            "commenting-feature"
          )
        )
      ) {
        //disable real-time and enable suggestions if user confirms
        enableCoEditing(false);
      } else {
        return false;
      }
    }
    wp.data.dispatch("core/editor").editPost({
      meta: { _sb_is_suggestion_mode: true },
    });
    wp.data.dispatch("mdstore").setSuggestionMode(true);

    var noticeMsg = sprintf(
      '%s <a href="https://docs.google.com/spreadsheets/d/1H0uksGbTMOy7f9fkSGXvkl1fwqO7ekShjo1j3JsOA6k/edit#gid=1835128986" target="_blank">%s</a>',
      __(
        "Suggestion mode is limited to a few blocks and actions only.",
        "commenting-feature"
      ),
      __("Check compatibility.", "commenting-feature")
    );
    showNotice(noticeMsg);
    multicollab_removeAllNotices();
    wp.data.dispatch("core/notices").removeNotice("suggestionModeOff");
    wp.data.dispatch("core/notices").createNotice(
      "success", // Can be one of: success, info, warning, error.
      __("Suggestion Mode is ON", "commenting-feature"), // Text string to display.
      {
        id: "suggestionModeOn",
        type: "snackbar",
        isDismissible: true, // Whether the user can dismiss the notice.
        // Any actions the user can perform.
      }
    );
    $(".cf-floating-wrapper__btn ul li:last-child").addClass("cf-suggestion-active");
  } else {
    wp.data.dispatch("core/editor").editPost({
      meta: { _sb_is_suggestion_mode: false },
    });
    wp.data.dispatch("mdstore").setSuggestionMode(false);
    multicollab_removeAllNotices();
    wp.data.dispatch("core/notices").removeNotice("suggestionModeOn");
    wp.data.dispatch("core/notices").createNotice(
      "success", // Can be one of: success, info, warning, error.
      __("Suggestion Mode is OFF", "commenting-feature"), // Text string to display.
      {
        id: "suggestionModeOff",
        type: "snackbar",
        isDismissible: true, // Whether the user can dismiss the notice.
        // Any actions the user can perform.
      }
    );
    $(".cf-floating-wrapper__btn ul li:last-child").removeClass("cf-suggestion-active");
  }
}

export const FindReact = (dom, traverseUp = 0) => {
  const key = Object.keys(dom).find((key) =>
    key.startsWith("__reactInternalInstance$")
  );
  const domFiber = dom[key];
  if (domFiber == null) return null;
  // react <16
  if (domFiber._currentElement) {
    let compFiber = domFiber._currentElement._owner;
    for (let i = 0; i < traverseUp; i++) {
      compFiber = compFiber._currentElement._owner;
    }
    return compFiber._instance;
  }

  // react 16+
  const GetCompFiber = (fiber) => {
    let parentFiber = fiber.return;
    while (typeof parentFiber.type == "string") {
      parentFiber = parentFiber.return;
    }
    return parentFiber;
  };
  let compFiber = GetCompFiber(domFiber);
  for (let i = 0; i < traverseUp; i++) {
    compFiber = GetCompFiber(compFiber);
  }
  return compFiber.stateNode;
}

export const createBoard = (selectedText, value, onChange) => {
  var referenceNode = document.getElementById("cf-comment-board-wrapper");
  var newNode = document.createElement("div");
  newNode.setAttribute("id", selectedText);
  newNode.setAttribute("class", "cls-board-outer  cm-board is_active");

  referenceNode.appendChild(newNode);

  container = document.getElementById(selectedText);
  const root = createRoot(container); // createRoot(container!) if you use TypeScript
  root.render(<Board datatext={selectedText} lastVal={value} onChanged={onChange} />);
  root.unmount();
}

/**
 * Displays a notice message for a short duration.
 *
 * This function displays a notice message in an element with the ID "cf-board-notice". The message is displayed for 3 seconds and then automatically hidden.
 *
 * @param {string} message - The message to display in the notice.
 */
export const showNotice = (message, status = 'info') => {
  const isNoticeContainer = document.querySelector('.cf-board-notice-top');
  const isEditorContent = document.querySelector('.interface-interface-skeleton__content, .block-editor-editor-skeleton__content, .edit-post-layout__content');

  if(isNoticeContainer){
    isNoticeContainer.remove();
  }

  const noticeContainer = document.createElement('div');
  noticeContainer.className = 'cf-board-notice-top cf-board-notice';

  if (isEditorContent) {
    isEditorContent.appendChild(noticeContainer);
  }
  
  const root = createRoot(noticeContainer);

  const handleDismiss = () => {
    root.unmount();
    noticeContainer.remove();
  };

  root.render(
    <Notice status={status} onRemove={handleDismiss} isDismissible>
      <div dangerouslySetInnerHTML={{ __html: message }} />
    </Notice>
  );
  setTimeout(handleDismiss, 10000);
}

/**
 * Updates the `data-rich-text-format-boundary` attribute on elements within the specified single board ID.
 *
 * This function iterates through all elements with the `data-rich-text-format-boundary="true"` attribute and updates the attribute based on the following conditions:
 *
 * 1. If the element has the `mdadded`, `mdremoved`, or `mdmodified` class, the attribute is set to `true` for the specified single board ID, and `false` for all other single board IDs.
 * 2. If the element's parent has the `mdadded`, `mdremoved`, or `mdmodified` class, the attribute is set to `true` for the specified single board ID, and `false` for all other single board IDs.
 * 3. If the element has the `mdspan-comment` class, the attribute is set to `true` for the specified single board ID, and `false` for all other single board IDs.
 *
 * @param {string} singleBoardId - The ID of the single board to update.
 * @param {HTMLElement} selectedBlock - The selected block element.
 */
export const updateRichTextFormatBoundary = (selectedNode, singleBoardId, selectedBlock) => {
  var underlineAllAttr = document.querySelectorAll('[data-rich-text-format-boundary="true"]');
  if (underlineAllAttr !== "undefined") {
    // Remove the attribute from each element
    underlineAllAttr.forEach(element => {
        element.removeAttribute('data-rich-text-format-boundary');
    });
    if (
      selectedNode.classList.contains("mdadded") ||
      selectedNode.classList.contains("mdremoved")
    ) {
      const singleUnderlineAllAttr = document.getElementById(selectedNode.id);
      if (singleBoardId === selectedNode.id && singleUnderlineAllAttr) {
        singleUnderlineAllAttr.setAttribute("data-rich-text-format-boundary", true);
      }
    } else if (
      selectedNode.parentNode.classList.contains("mdmodified") ||
      selectedNode.parentNode.classList.contains("mdremoved") ||
      selectedNode.parentNode.classList.contains("mdadded")
    ) {
      const parentUnderlineAllAttr = document.getElementById(selectedNode.parentNode.id);
      if (singleBoardId === selectedNode.parentNode.id && parentUnderlineAllAttr) {
        const children = parentUnderlineAllAttr.children;
        for (let i = 0; i < children.length; i++) {
          children[i].setAttribute("data-rich-text-format-boundary", true);
        }
      }
    } else if (selectedNode.classList.contains("mdspan-comment")) {
      var suggestionId = selectedNode.getAttribute("datatext");
      const getDataTextId = selectedBlock.querySelector('[datatext="' + suggestionId + '"]');
      if (singleBoardId === suggestionId && getDataTextId) {
        getDataTextId.setAttribute("data-rich-text-format-boundary", true);
      }
    }
  }
}

/**
 * Handles the floating of the whole block comment and other related UI elements when certain events occur.
 *
 * This function is responsible for managing the behavior of the whole block comment and related UI elements, such as the floating icon, when certain events are triggered. It handles cases where the target element is a comment, table, or other formatting elements, and updates the UI accordingly.
 *
 * @param {Event} event - The event object that triggered the function.
 * @returns {void}
 */
export const floatWholeBlockNonTextBoard = (event, selector) => {
  const iframe = cfGetIframe();
  const iframeDocument = iframe ? iframe.contentWindow.document : null;
  const block = select("core/block-editor").getSelectedBlock();
  // Gets the top position of the parent element with the class 'interface-interface-skeleton__body'.
  const parentElement = document.querySelector('.interface-interface-skeleton__body');
  const parentRect = parentElement.getBoundingClientRect().top - 15;
  if (
    event.target.matches(".cf-icon-wholeblock__comment") ||
    event.target.closest(".cf-icon-wholeblock__comment") ||
    'core/table' !== block?.name //Fix Git issue #1617 as this was stopping the floating icon to display on older versions of WordPress.
  ) {
    // Fixed for the inner elements resolved 627 @author - Mayank / 3.6
    event.stopPropagation(); // Prevent event bubbling
  }
  let focusElement;
  if(iframeDocument){
    focusElement = iframeDocument.activeElement.localName;
  } else {
    focusElement = document.activeElement.localName;
  }
  var selectedText;
  var selectedBlock;
  let floatText = [];
  const bodyUpdateIds = [];
  let hasTableBodyUpdate, insBlockId, tableRowColumnSgId, tableColumnAlignSgId, commentId, topOfTextElement, tableWholeBlockCommentId, tableBlockAlignId, delBlockId;
  if ('core/table' === block?.name) {
    
    tableWholeBlockCommentId = event.target.closest(selector).closest('figure.is-selected.wp-block-table')?.getAttribute("datatext");
    tableBlockAlignId = event.target.closest(selector).closest('figure.is-selected.wp-block-table')?.getAttribute("align_sg_id");
    if (tableWholeBlockCommentId !== null || tableBlockAlignId !== null) {
      hasTableBodyUpdate = true;
    }

    $(".cf-bodyrowupdate, .cf-columnalign, .cf-bodycolumnupdate, .cf-bodycolumndelete, .cf-bodyrowdeleteupdate").removeClass("is-selected");
    let childNodes;
    let targetTag = event.target.tagName.toLowerCase();
    let targetParentTag = event.target?.parentNode?.tagName.toLowerCase();
    if (targetTag === 'td' || targetTag === 'div') {
      // It's an <td> tag
      childNodes = event?.target?.childNodes;
    } else if (targetTag === 'ins' || targetTag === 'del') {
      // It's an <ins> or <del> tag
      childNodes = event?.target?.parentNode?.childNodes;
      insBlockId = event.target.getAttribute('id');
      bodyUpdateIds.push(insBlockId);
    } else if (targetTag === 'mdspan') {
      // It's an <mdspan> tag
      if (targetParentTag === 'ins' || targetParentTag === 'del') {
        childNodes = event?.target?.parentNode?.parentNode?.childNodes;
        insBlockId = event.target?.parentNode?.getAttribute('id');
        bodyUpdateIds.push(insBlockId);
      } else if (targetParentTag === 'td') {
        childNodes = event?.target?.parentNode?.childNodes;
      }
      commentId = event.target.getAttribute('datatext');
      bodyUpdateIds.push(commentId);
    } else if (event.target?.closest('del') || event.target?.closest('ins')) { //for other formatting bold, italics with del and ins tag
      childNodes = event?.target?.closest('.block-editor-rich-text__editable')?.childNodes;
      insBlockId = event.target?.closest('ins')?.getAttribute('id');
      delBlockId = event.target?.closest('del')?.getAttribute('id');
    }

    if (childNodes) {
      for (let i = 0; i < childNodes.length; i++) {
        const childNode = childNodes[i];
        const cList = childNode.classList;
        if (cList) {
          if (cList.contains('bodyupdate-row') || cList.contains('bodyupdate-column') || cList.contains('bodyupdate-delete-row') || cList.contains('bodyupdate-delete-column')) {
            const idValue = childNode.getAttribute('id');
            if (idValue) {
              bodyUpdateIds.push(idValue);
              hasTableBodyUpdate = true;
              tableRowColumnSgId = idValue;
              topOfTextElement = tableRowColumnSgId;
              if (!document.body.classList.contains('hide-sg') && (cList.contains('bodyupdate-row') || cList.contains('bodyupdate-delete-row'))) {
                if(iframeDocument){
                  iframeDocument.getElementById(idValue).closest('tr').classList.add('is-selected');
                }else{
                  document.getElementById(idValue).closest('tr').classList.add('is-selected');
                }
              }

              if (!document.body.classList.contains('hide-sg') && (cList.contains('bodyupdate-column') || cList.contains('bodyupdate-delete-column'))) {
                let allElements;
                if(iframeDocument){
                  allElements = iframeDocument.querySelectorAll(`[id="${idValue}"]`);
                }else{
                  allElements = document.querySelectorAll(`[id="${idValue}"]`);
                }
                allElements.forEach(function (element) {
                  element.closest('td').classList.add('is-selected')
                });
              }
            }
          } else if (cList.contains('columnalign')) {
            const idValue = childNode.getAttribute('id');
            bodyUpdateIds.push(idValue);
            hasTableBodyUpdate = true;
            tableColumnAlignSgId = idValue;
            topOfTextElement = tableColumnAlignSgId;
            if (!document.body.classList.contains('hide-sg')) {
              let allElements;
              if(iframeDocument){
                allElements = iframeDocument.querySelectorAll(`[id="${idValue}"]`);
                iframeDocument.getElementById(idValue).closest('td').classList.add('is-selected');
              }else{
                allElements = document.querySelectorAll(`[id="${idValue}"]`);
                document.getElementById(idValue).closest('td').classList.add('is-selected');
              }
              allElements.forEach(function (element) {
                element.closest('td').classList.add('is-selected')
              });
            }
          }
        }
      }
    }
    if (undefined === hasTableBodyUpdate) {
      return;
    }
  }

  if (
    event.target.classList.contains("cf-icon__addBlocks") ||
    event.target.classList.contains("cf-icon__removeBlocks")
  ) {
      if(iframeDocument){
        selectedBlock = event.target.getAttribute("data-suggestion_id") || iframeDocument.querySelector("#block-" + event.target.getAttribute("data-blockclient_id")).getAttribute("suggestion_id"); 
      }else{
        selectedBlock = event.target.getAttribute("data-suggestion_id") || document.querySelector("#block-" + event.target.getAttribute("data-blockclient_id")).getAttribute("suggestion_id"); 
      }
       
  } else if (hasTableBodyUpdate) {
    floatText.push(insBlockId);
    floatText.push(tableRowColumnSgId);
    floatText.push(tableColumnAlignSgId);
    floatText.push(commentId);
    floatText.push(tableWholeBlockCommentId);
    floatText.push(tableBlockAlignId);
    floatText.push(delBlockId);
  } else {
    //change code to support whole block comment/@author:Pooja/since 3.4
    const target = event.target.closest(selector);
    if (target && typeof target.getAttribute === 'function') {
        selectedText = target.getAttribute("datatext");
        selectedBlock = target.getAttribute("data-suggestion_id");
        if (!selectedText) {
            const commentIcon = target.querySelector(".commentIcon");
            if (commentIcon && typeof commentIcon.getAttribute === 'function') {
                selectedText = commentIcon.getAttribute("datatext");
            }
        }

        floatText.push(selectedText);
        floatText.push(selectedBlock);
    }
  }

  wp.data.dispatch("mdstore").setDataText(selectedText);
  if ("figcaption" === focusElement) {
    return;
  }
  
  if ("undefined" !== selectedText || "undefined" !== selectedBlock) {
    
    // Remove multiple classes from elements
    if(iframeDocument){
      iframeDocument.querySelectorAll(`
        .cls-board-outer,
        .cls-board-outer .buttons-wrapper,
        .cf-icon__addBlocks,
        .cf-icon__removeBlocks,
        .cf-icon-wholeblock__comment,
        .cf-onwhole-block__comment
      `).forEach(element => {
        element.classList.remove("focus", "is-open", "active");
      });
    } else {
      document.querySelectorAll(`
        .cls-board-outer,
        .cls-board-outer .buttons-wrapper,
        .cf-icon__addBlocks,
        .cf-icon__removeBlocks,
        .cf-icon-wholeblock__comment,
        .cf-onwhole-block__comment
      `).forEach(element => {
        element.classList.remove("focus", "is-open", "active");
      });
    }

    // Remove "show" class from all elements with the class "comment-delete-overlay" inside "#cf-comment-board-wrapper"
    document.querySelectorAll("#cf-comment-board-wrapper .comment-delete-overlay").forEach(element => {
      element.classList.remove("show");
    });

    // Uncheck all checkboxes with the class "resolve-cb" inside ".comment-resolve" inside "#cf-comment-board-wrapper"
    document.querySelectorAll("#cf-comment-board-wrapper .comment-resolve .resolve-cb").forEach(element => {
      element.checked = false;
    });

    // Set styles for elements with the class "cls-board-outer" inside "#cf-comment-board-wrapper"
    document.getElementById("cf-comment-board-wrapper")?.classList.remove("cf-unset-all");
    document.querySelectorAll("#cf-comment-board-wrapper .cls-board-outer").forEach(element => {
      element.style.top = "";
      //element.style.opacity = "0.2";
      element.classList.remove("focus", "onGoing", "is-open");
    });

    if(iframeDocument){
      iframeDocument.querySelectorAll("mdspan").forEach(element => {
        element.removeAttribute("data-rich-text-format-boundary");
      });
    } else {
      document.querySelectorAll("mdspan").forEach(element => {
        element.removeAttribute("data-rich-text-format-boundary");
      });
    }

    let realTimeMode = wp.data.select('core/editor').getEditedPostAttribute('meta')?._is_real_time_mode;
    if (true !== realTimeMode) {
      if(iframeDocument){
        iframeDocument.querySelectorAll('.btn-wrapper').forEach(element => {
          element.style.display = 'none';
        });
      } else {
        document.querySelectorAll('.btn-wrapper').forEach(element => {
          element.style.display = 'none';
        });
      }
    }

    let selectedDataText;
    if(iframeDocument){
      selectedDataText = iframeDocument.querySelector('[datatext="' + selectedText + '"]');
    }else{
      selectedDataText = document.querySelector('[datatext="' + selectedText + '"]');
    }
    if (selectedDataText && selectedDataText.classList.contains("cf-icon-wholeblock__comment")) {
      selectedDataText.classList.add("focus");
    }
    let windowScrollY;
    const getWindowClass = getScrollClass();
    const windowScrollYSelector = document.querySelector(getWindowClass);
    if (windowScrollYSelector) {
      windowScrollY = windowScrollYSelector.scrollTop;
    }
    if (event.target.classList.contains("cf-icon__addBlocks") ||
        event.target.classList.contains("cf-icon__removeBlocks") ||
        event.target.classList.contains("cf-icon-wholeblock__comment")
    ) {
      
      let cfIconCommentId = event.target.getAttribute("datatext");
      let cfIconSuggetionId = event.target.getAttribute("data-suggestion_id");

      let topOfTextSingleBoard;
      let combineBoardId = [];
      let boardOuterHeight = 0;

      if (cfIconSuggetionId) {
        let getSingleSugBoardId;
        if(iframeDocument){
          getSingleSugBoardId = iframeDocument.querySelector('[data-suggestion_id="' + cfIconSuggetionId + '"]');
        } else {
          getSingleSugBoardId = document.querySelector('[data-suggestion_id="' + cfIconSuggetionId + '"]');
        }
        getSingleSugBoardId.classList.add("focus");
        event.target.classList.add("focus");
        topOfTextSingleBoard = getSingleSugBoardId.getBoundingClientRect().top; 
        combineBoardId.push("sg" + cfIconSuggetionId);
      }
      if(cfIconCommentId) {
        let getSingleCmtBoardId;
        if(iframeDocument){
          getSingleCmtBoardId = iframeDocument.querySelector('[datatext="' + cfIconCommentId + '"]');
        } else {
          getSingleCmtBoardId = document.querySelector('[datatext="' + cfIconCommentId + '"]');
        }
        getSingleCmtBoardId.classList.add("focus");
        event.target.classList.add("focus");
        topOfTextSingleBoard = getSingleCmtBoardId.getBoundingClientRect().top;
        combineBoardId.push(cfIconCommentId);
      }
      if(combineBoardId){
        for (var i = 0; i < combineBoardId.length; i++) {
          const elementcombineBoardId = document.getElementById(combineBoardId[i]);
          if (elementcombineBoardId) {
            //elementcombineBoardId.style.opacity = "1";
            elementcombineBoardId.classList.add("focus", "onGoing", "is-open");
            elementcombineBoardId?.parentElement?.classList.add("cf-unset-all");
            if(iframeDocument){  
              jQuery("#" + combineBoardId[i]).offset({
                top: topOfTextSingleBoard + boardOuterHeight + 50,
              });

            } else {
              jQuery("#" + combineBoardId[i]).offset({
                top: topOfTextSingleBoard + boardOuterHeight + 50,
              });

            }
          }

          if(combineBoardId.length > 1){
            boardOuterHeight = boardOuterHeight + document.querySelector("#" + combineBoardId)?.offsetHeight + 20 ||
            "";
          }
        }
      }

    } else {
      let boardOuterHeight = 0;
      let addExtraSpace = 0;
      if(iframeDocument){
        addExtraSpace = 50;
      }
      if (selectedText) {
        let getSingleCmtBoardId;
        if(iframeDocument){
          getSingleCmtBoardId = iframeDocument.querySelector('[datatext="' + selectedText + '"]');
        } else {
          getSingleCmtBoardId = document.querySelector('[datatext="' + selectedText + '"]');
        }
          const topOfTextSingleBoard = getSingleCmtBoardId.getBoundingClientRect().top ? getSingleCmtBoardId.getBoundingClientRect().top : 0;
          const selectedTextElement = document.getElementById(selectedText);
          if (selectedTextElement) {
            //selectedTextElement.style.opacity = "1";
            selectedTextElement.classList.add("focus", "onGoing", "is-open");
            selectedTextElement?.parentElement?.classList.add("cf-unset-all");
            jQuery("#" + selectedText).offset({
              top: topOfTextSingleBoard + addExtraSpace,
            });

            boardOuterHeight = boardOuterHeight + document.querySelector("#" + selectedText)?.offsetHeight + 20 ||
            "";
          }
      }
      const customAttrSuggestion = cfgetCustomAttribute();
      let boardCount = 0;
      customAttrSuggestion.map((attrValue, i) => {
        let getSgId = event.target.closest(selector).getAttribute(attrValue) || "";
        if(getSgId){
          let getSingleSugBoardId;
          if(iframeDocument){
            getSingleSugBoardId = iframeDocument.querySelector(`[${attrValue}="${getSgId}"]`);
          } else {
            getSingleSugBoardId = document.querySelector(`[${attrValue}="${getSgId}"]`);
          }
          
          const topOfTextSingleBoard = getSingleSugBoardId
            ? (getSingleSugBoardId.getBoundingClientRect().top < 12 
                ? 12 
                : getSingleSugBoardId.getBoundingClientRect().top)
            : 0;
          const combineBoardId = "sg" + getSgId;

          const elementcombineBoardId = document.getElementById(combineBoardId);
          if (elementcombineBoardId) {
            //elementcombineBoardId.style.opacity = "1";
            elementcombineBoardId?.parentElement?.classList.add("cf-unset-all");
            elementcombineBoardId.classList.add("onGoing", "is-open");
            if( boardCount === 0 && null === selectedText ) {
              elementcombineBoardId.classList.add("focus");
            }
            boardCount++;
           
            jQuery("#" + combineBoardId).offset({
              top: topOfTextSingleBoard + boardOuterHeight + addExtraSpace,
            });
          }

          boardOuterHeight = boardOuterHeight + document.querySelector("#" + combineBoardId)?.offsetHeight + 20 ||
            "";
        }
      });
      wp.data.dispatch("mdstore").setIsActive(true);
    }
    jQuery.event.trigger({ type: "showHideComments" });
  }
}

/**
 * Opens the comment board sidebar in the WordPress editor.
 *
 * This function opens the "edit-post/cf-collab-sidebar" sidebar in the WordPress editor. It first checks if the current active sidebar is not the comment board sidebar, and if so, it dispatches an action to open the comment board sidebar.
 *
 * @returns {Promise<void>} A Promise that resolves when the sidebar has been opened.
 */
export const openCommentBoardSidebar = () => {
  return new Promise((resolve, reject) => {
    try {
      const sidebarName = select("core/edit-post").getActiveGeneralSidebarName();

      if (sidebarName !== "edit-post/cf-collab-sidebar") {
        dispatch("core/edit-post").openGeneralSidebar("edit-post/cf-collab-sidebar");
      }
      resolve(); // Resolve the promise after the sidebar is opened
    } catch (error) {
      reject(error); // Reject the promise if there is an error
    }
  });
};

/**
 * Generates board IDs based on the provided singleBoardId.
 *
 * @param {string} singleBoardId - The single board ID.
 * @returns {Object} - An object containing the generated board IDs.
 * @property {string|null} singleBoardIdSuggestion - The single board ID for suggestions.
 * @property {string|null} singleBoardIdComment - The single board ID for comments.
 * @property {string|null} combineBoardId - The combined board ID.
 */
export const getBoardIds = (singleBoardId) => { 

  let boardIds = { singleBoardIdSuggestion: null, singleBoardIdComment: null, combineBoardId: null };

  if (singleBoardId.match(/^el/m) === null) {
    boardIds.singleBoardIdSuggestion = "sg" + singleBoardId;
    boardIds.combineBoardId = "sg" + singleBoardId;
  } else {
    boardIds.singleBoardIdComment = singleBoardId;
    boardIds.combineBoardId = singleBoardId;
  }

  return boardIds;
};

/**
 * Positions a floating element relative to a reference element, adjusting the position based on the height of any previous elements.
 *
 * @param {HTMLElement} referenceElement - The reference element to position the floating element relative to.
 * @param {HTMLElement} floatingElement - The floating element to be positioned.
 * @param {number} i - The index of the current element in the `selectedText` array.
 * @param {string[]} selectedText - An array of selected text elements.
 * @returns {Promise<void>} - A Promise that resolves when the floating element has been positioned.
 */
export const positionFloatingElement = async (referenceElement, floatingElement, i, selectedText, isMedia = false) => {  
  if (referenceElement && floatingElement) {
    let { y } = await computePosition(referenceElement, floatingElement, {
      placement: 'top',
      modifiers: [
        offset({ mainAxis: 10, crossAxis: 10 }),
        shift({ padding: 5 }),
        flip(),
      ],
    });
    if (i > 0) {
      
      for (let j = 0; j < i; j++) {
        const prevSingleBoardId = selectedText[j];
        const { combineBoardId } = getBoardIds(prevSingleBoardId);
        const prevElement = document.getElementById(combineBoardId);
        
        if (prevElement) {
          const prevElementHeight = prevElement.offsetHeight;
          if (isMedia) {
            y += prevElementHeight + 40; // Adjust the y-position based on previous element height
          } else {
            y += prevElementHeight + 10; // Adjust the y-position based on previous element height
          }
        }
      }
    }
    floatingElement.style.top = `${y + 150}px`;
    
  } else {
    console.error("Reference or floating element is not available.");
  }
};
