import allowedBlocks from "../common/component/compatibility/allowedBlocks";
import Comment from "./comment";
import ContentEditable from "react-contenteditable";
import icons from "../common/component/icons";
import PropTypes from "prop-types";
import React from 'react';
import { undoRedoFun } from '../common/component/undoRedo';
import { showNotice } from '../common/utils';

const { __, sprintf } = wp.i18n; // eslint-disable-line
const { createRef } = wp.element;
const { dispatch, select} = wp.data;
const { removeFormat } = wp.richText; // eslint-disable-line
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);

export default class Board extends React.Component {
  constructor(props) {
    super(props);
    this.contentEditable = React.createRef();
    this.displayComments = this.displayComments.bind(this);
    this.updateComment = this.updateComment.bind(this);
    this.removeComment = this.removeComment.bind(this);
    this.addNewComment = this.addNewComment.bind(this);
    this.cancelComment = this.cancelComment.bind(this);

    const currentPostID = wp.data.select("core/editor").getCurrentPostId(); // eslint-disable-line
    const postSelections = [];
    let selectedText;
    let txtselectedText;
    let metaselectedText;

    // `this` is the div
    selectedText = this.props.datatext;
    txtselectedText = "txt" + selectedText;
    metaselectedText = "_" + selectedText;
    setTimeout(function () {
      const textarea = document.querySelector(`#${selectedText} textarea`);
      if (textarea) {
          textarea.setAttribute("id", txtselectedText);
      }
    }, 3000);

    this.commentedOnText = this.props.commentedOnText;
    // Initial state
    this.state = {
      comments: [],
      newcommentText: "",
      hasComments: 0,
      commentedOnText: null,
      assignedTo: null,
    };

    if (1 !== this.props.freshBoard) {
      this.fetchCommentData = this.fetchCommentData.bind(this);
    } else {
      try {
        this.currentUserName = select("core").getCurrentUser().name;
        const currentUserProfile = select("core").getCurrentUser().avatar_urls;
        this.currentUserProfile =
          currentUserProfile[Object.keys(currentUserProfile)[1]];
      } catch (e) {
        this.currentUserName = localStorage.getItem("userName");
        this.currentUserProfile = localStorage.getItem("userURL");
      }
    }
  }

  handleFetchedComments(commentsData) {

    const { userDetails, resolved, commentedOnText, assignedTo } = commentsData;

    const iframe = cfGetIframe();
    const iframeDocument = iframe ? iframe.contentWindow.document : null;
  
    this.commentedOnText =
      this.commentedOnText !== undefined
        ? this.commentedOnText
        : commentedOnText;
    this.assignedTo = assignedTo;
  
    if (resolved === 'true' || !userDetails || userDetails.length === 0 || '' === this.commentedOnText) {
      let elIDRemove = this.props.datatext;
      let elementSelectedText;

      

      if(iframeDocument){
        elementSelectedText = iframeDocument.querySelector(`[datatext="${elIDRemove}"]`);
      }else{
        elementSelectedText = document.querySelector(`[datatext="${elIDRemove}"]`);
      }

      if (elementSelectedText) {
        elementSelectedText.classList.remove('commentIcon');
        
        const el = document.getElementById(elIDRemove);
        if (el) el.remove();
        removeTag(elIDRemove);
      }
      return;
    }
  
    const postSelections = userDetails.map((val) => val);
    this.hasComments = postSelections.length > 0 ? 1 : 0;

    this.setState({ comments: postSelections });
  }
  
  fetchCommentData(currentPostID, metaselectedText, currentUserID) {
    const fetchedCommentCache = select('mdstore').getFetchedCommentCache();
    const cacheKey = `${currentPostID}-${metaselectedText}`;  
    // Serve from cache if available
    if (fetchedCommentCache[cacheKey]) {
      this.handleFetchedComments(fetchedCommentCache[cacheKey]);
      return;
    }
  
    wp.apiFetch({
        path: `/multicollab/multicollab-get-comments-api/?currentPostID=${currentPostID}&elID=${metaselectedText}&currentUserID=${currentUserID}`,
      })
        .then((fps) => {
          dispatch('mdstore').setFetchedCommentCache(cacheKey, fps);
          this.handleFetchedComments(fps);
        })
        .catch((error) => {
          console.error('Error fetching comments:', error);
        });
  }
  removeAttachment(idx, cTimestamp, elID, attachmentText) {
    elID = "_" + elID;
    // Activate 'Save Draft' or 'Publish' button

    const attachmentTextElement = document.querySelector(`#${cTimestamp} .attachment-text`);
    if (attachmentTextElement) {
        attachmentTextElement.innerHTML = "";
    }

    // for empty attach icon remove - code added by meet
    const thumbFileElement = document.querySelector(`#${cTimestamp} #cf_thumb_file`);
    if (thumbFileElement) {
        thumbFileElement.innerHTML = "";
    }
    
      dispatch("core/editor")
      .editPost({ meta: { reflect_comments_changes: 1 } }); // eslint-disable-line
  }

  removeComment(idx, cTimestamp, elID) {
    var arr = this.state.comments;

    arr.splice(idx, 1);
    const CurrentPostID = wp.data.select("core/editor").getCurrentPostId(); // eslint-disable-line
    elID = "_" + elID;
    var data = {
      action: "multicollab_delete_comment",
      currentPostID: CurrentPostID,
      timestamp: cTimestamp,
      metaId: elID,
    };
    // Convert data to URL-encoded string
    const formData = new URLSearchParams(data).toString();
 
    // Use fetch API to make the POST request
    fetch(ajaxurl, {
      method: 'POST',
      headers: {
          'Content-Type': 'application/x-www-form-urlencoded',
      },
      body: formData,
  })
  .then(response => response.text())
  .then(() => {
      dispatch("core/editor")
          .editPost({ meta: { reflect_comments_changes: 1 } });  
      const cacheKey = `${CurrentPostID}-${elID}`;
      const fetchedCommentCache = select('mdstore').getFetchedCommentCache();
      // check iif the comment is in the cache
      if (fetchedCommentCache[cacheKey]) {
        delete fetchedCommentCache[cacheKey]; // Remove the specific entry
        wp.data.dispatch('mdstore').setFetchedCommentCache(fetchedCommentCache); // Dispatch the updated comment cache
      }     
  })
  .catch(error => console.error('Error:', error));

  this.setState({ comments: arr, newcommentText: "" });
    const cfPostStatus = select('core/editor').getCurrentPost().status;
      if (cfPostStatus === 'publish') {
        dispatch('core/editor').savePost();
      } else {
        dispatch('core/editor').autosave();
      }
  }

   /**
   * Updates a comment in the comments array and saves the changes to the post's comments in the editor.
   *
   * This function is responsible for updating an existing comment in the comments array, and dispatching an action to the core/editor store to reflect the changes to the post's comments.
   *
   * @param {string} newText - The new text content of the comment.
   * @param {number} idx - The index of the comment in the comments array.
   * @param {string} cTimestamp - The timestamp of the comment.
   * @param {string} dateTime - The date and time of the comment.
   * @param {string} metaID - The ID of the comment element.
   * @param {string} editedTime - The time the comment was edited.
   * @param {string} editedTimestamp - The timestamp of the edited comment.
   * @param {string} assignedText - The assigned text of the comment.
   * @param {string} attachmentText - The attachment text of the comment.
   */
  updateComment(
    newText,
    idx,
    cTimestamp,
    dateTime,
    metaID,
    editedTime,
    editedTimestamp,
    assignedText,
    attachmentText
  ) {
    var arr = this.state.comments;
    var userID = "";
    var userName = "";
    var userRole = "";
    var userProfile = "";
    try {
      userID = select("core").getCurrentUser().id;  
      userName = select("core").getCurrentUser().name;  
      userRole = select("core").getUser(userID).roles[0];  
      userProfile = select("core").getCurrentUser().avatar_urls;  
      userProfile = userProfile[Object.keys(userProfile)[1]];
    } catch (e) {
      userID = localStorage.getItem("userID");
      userName = localStorage.getItem("userName");
      userRole = localStorage.getItem("userRole");
      userProfile = localStorage.getItem("userURL");
    }

    var newArr = {
      userName: userName,
      userRole: userRole,
      profileURL: userProfile,
      dtTime: dateTime,
      thread: newText,
      userData: userID,
      index: idx,
      status: "publish",
      timestamp: cTimestamp,
      editedTime: editedTime,
      editedTimestamp: editedTimestamp,
      assignedText: assignedText,
      attachmentText: attachmentText
  };
  arr[idx] = newArr;
  const CurrentPostID = select("core/editor").getCurrentPostId();  
  metaID = "_" + metaID;
    var data = {
      action: "multicollab_update_comment",
      nonce:
        typeof window.multicollabAdminL10n !== "undefined" &&
        window.multicollabAdminL10n.nonce
          ? window.multicollabAdminL10n.nonce
          : "",
      currentPostID: CurrentPostID,
      editedComment: JSON.stringify(newArr),
      metaId: metaID,
    };

     // Convert data to URL-encoded string
     const formData = new URLSearchParams(data).toString();

    // since 2.8 ajaxurl is always defined in the admin header and points to admin-ajax.php
    var _this = this;
         // Use fetch API to make the POST request
      fetch(ajaxurl, {
          method: 'POST',
          headers: {
              'Content-Type': 'application/x-www-form-urlencoded',
          },
          body: formData,
      })
      .then(response => response.json())
      .then(data => {
          if (data.error !== undefined) {
              alert(data.error);
              return false;
          }

          // Activate 'Save Draft' or 'Publish' button
          dispatch("core/editor").editPost({ meta: { reflect_comments_changes: 1 } });  

          // Replace content with filtered HTML (without HTML tags) from AJAX response
          if (data.arr.thread) {
              arr[idx].thread = data.arr.thread;
          }

          const cacheKey = `${CurrentPostID}-${metaID}`;
          const fetchedCommentCache = select('mdstore').getFetchedCommentCache();
          // check iif the comment is in the cache
          if (fetchedCommentCache[cacheKey]) {
            delete fetchedCommentCache[cacheKey]; // Remove the specific entry
            wp.data.dispatch('mdstore').setFetchedCommentCache(fetchedCommentCache); // Dispatch the updated comment cache
          } 

          // Update comment data store to display in activities without refresh
          const threadsGlobalData = select("mdstore").getAllCommentCount();
          if (threadsGlobalData?.length !== undefined) {
              for (let i = 0; i < threadsGlobalData[idx]?.activities?.length; i++) {
                  if (threadsGlobalData[idx].activities[i].id === data.arr.timestamp) {
                      threadsGlobalData[idx].activities[i].thread = data.arr.thread;
                      dispatch("mdstore").setAllCommentCount(threadsGlobalData);
                  }
              }
          }

          this.setState({ comments: arr });
          const cfPostStatus = select('core/editor').getCurrentPost().status;
          if (cfPostStatus === 'publish') {
            dispatch('core/editor').savePost();
          } else {
            dispatch('core/editor').autosave();
          }
      })
      .catch(error => console.error('Error:', error));
  }

  /**
   * Adds a new comment to the board.
   *
   * This function is responsible for handling the addition of a new comment to the board. It performs the following tasks:
   *
   * 1. Checks if the current user is already added to the `_realtime_collaborators` meta. If not, it adds the current user's details to the meta.
   * 2. Retrieves the current user's information, including their ID, role, username, and profile picture.
   * 3. Constructs a new comment object with the necessary data, such as the comment text, user information, and other metadata.
   * 4. Sends the new comment data to the server using the `fetch` API and handles the response.
   * 5. Updates the state of the component with the new comment, activates the 'Save Draft' or 'Publish' button, and updates the comment data store.
   * 6. Clears the comment input field and the attachment text.
   *
   * @param {Event} event - The event object associated with the comment addition.
   * @returns {void}
   */
  addNewComment(event) {
    const iframe = cfGetIframe();
    const iframeDocument = iframe ? iframe.contentWindow.document : null;

    const clientId = wp.data.select('core/block-editor').getSelectedBlockClientId();
    event.preventDefault();
    const { datatext, mediaId, mediaUrl } = this.props;
    var currentTextID = "txt" + datatext;
    // Prefer controlled state (same source as the enabled/disabled Reply button); DOM can lag behind react-contenteditable.
    var newText =
      typeof this.state.newcommentText === "string" &&
      this.state.newcommentText.trim() !== ""
        ? this.state.newcommentText
        : document.getElementById(currentTextID)?.innerHTML ?? "";
    var attachmentText = document.getElementById("cf_thumb_file")?.innerHTML;

    newText = filterTextBeforeSave(newText);

    let newTextstring = validateCommentReplyText(newText);

    if ("" !== newText && "" !== newTextstring && /\S/g.test(newTextstring)) {
      var userID = "";
      var userName = "";
      var userRole = "";
      var userProfile = "";
      try {
        userID = select("core").getCurrentUser().id;  
        userRole = select("core").getUser(userID).roles[0];  
        userName = select("core").getCurrentUser().name;  
    } catch (e) {
        userID = localStorage.getItem("userID");
        userName = localStorage.getItem("userName");
        userRole = localStorage.getItem("userRole");
    }

    if ("1" === localStorage.getItem("showAvatars")) {
      userProfile = select("core").getCurrentUser().avatar_urls;  
      userProfile = userProfile[Object.keys(userProfile)[1]];
  } else {
      userProfile = localStorage.getItem("userURL");
  }

      let blockType = wp.data.select('core/block-editor').getSelectedBlock()?.name;

      if (allowedBlocks.media.includes(blockType)) {
          blockType = blockType;
      } else {
          if (!allowedBlocks.text.includes(blockType) && undefined !== blockType && null !== blockType) {
              blockType = "md-block";
          } else {
              blockType = "";
          }
      }
      var newArr = {};
      newArr["userData"] = userID;
      newArr["thread"] = newText;
      {
        const fromProps =
          undefined !== this.commentedOnText ? this.commentedOnText : "";
        const fromExistingThread =
          Array.isArray(this.state.comments) &&
          this.state.comments.length > 0 &&
          this.state.comments[0] &&
          this.state.comments[0].commentedOnText
            ? this.state.comments[0].commentedOnText
            : "";
        newArr["commentedOnText"] =
          fromProps !== "" ? fromProps : fromExistingThread;
      }
      newArr["userName"] = userName;
      newArr["userRole"] = userRole;
      newArr["profileURL"] = userProfile;
      newArr["status"] = "publish";
      newArr["blockType"] = blockType;
      newArr["attachmentText"] = attachmentText;

      const CurrentPostID = select("core/editor").getCurrentPostId();  

      var el = currentTextID.substring(3);
      var metaId = "_" + el;
      var assignTo = "";
      if (document.querySelector(`#${el} .cf-assign-to-user`)?.checked) {
        assignTo = document.querySelector(`#${el} .cf-assign-to-user`).value;
    }
      newArr["assigned"] = assignTo;
      var arr = Array.isArray(this.state.comments)
        ? [...this.state.comments]
        : [];
      arr.push(newArr);
      var data = {
        action: "multicollab_add_comment",
        nonce:
          typeof window.multicollabAdminL10n !== "undefined" &&
          window.multicollabAdminL10n.nonce
            ? window.multicollabAdminL10n.nonce
            : "",
        currentPostID: CurrentPostID,
        commentList: JSON.stringify(arr),
        metaId: metaId,
        assignTo: assignTo,
        blockType: blockType,
      };

      document.querySelector(`#${el} .shareCommentContainer`).classList.add("loading");
      let _this = this;
      const event = new Event('editorLayoutUpdate');
      document.dispatchEvent(event);
      fetch(ajaxurl, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
        },
        body: new URLSearchParams(data).toString(),
    })
    .then((response) => {
      if (!response.ok) {
        return Promise.reject(new Error(response.statusText || `HTTP ${response.status}`));
      }
      return response.json();
    })
    .then(data => {
        setBoardIdByValue(el, clientId);
        document.querySelector(`#${el} .shareCommentContainer`).classList.remove("loading");
        document.querySelectorAll(".fresh-board").forEach(el => el.classList.remove("fresh-board"));

        if (data.error !== undefined) {
            alert(data.error);
            return false;
        }
        arr[arr.length - 1]["dtTime"] = data.dtTime;
        arr[arr.length - 1]["timestamp"] = data.timestamp;
        arr[arr.length - 1]["assignedText"] = data.assignedText;

        // Updating the assigned user info. Use != null so undefined does not slip through (!== null is true for undefined).
        if (data.assignedTo != null) {
          const assignedPayload = data.assignedTo;
          const resolvedDisplayName =
            assignedPayload.display_name ||
            assignedPayload.username ||
            "";
          const displayName = resolvedDisplayName
            ? resolvedDisplayName
            : __("Unknown User", "commenting-feature");

          var assignedUserDetails = `
              <div class="cf-board-assigned-to" data-user-id="${assignedPayload.ID ?? ""}" data-user-email="${assignedPayload.user_email ?? assignedPayload.email ?? ""}">
                  <div class="assigned-user-details">
                      <div class="user-avatar">
                          <img src="${assignedPayload.avatar ?? ""}" alt="${resolvedDisplayName}" />
                      </div>
                      <div class="user-info">
                          <span class="badge"> ${__("Assigned to", "commenting-feature")}</span>
                          <p class="display-name">${__(displayName, "commenting-feature")}</p>
                      </div>
                  </div>
              </div>
          `;
          const assignedElement = document.querySelector(`#${el} .cf-board-assigned-to`);
          if (assignedElement) {
              assignedElement.remove();
          }
          const boardTopElement = document.querySelector(`#${el} .boardTop`);
          if (boardTopElement) {
              boardTopElement.insertAdjacentHTML('beforebegin', DOMPurify.sanitize(assignedUserDetails));
          }
      }

        // Update hasComment prop for dynamic button text.
        _this.hasComments = 1;

        //Update Freshboard value for dynamic button text

        // Activate 'Save Draft' or 'Publish' button
        dispatch("core/editor").editPost({ meta: { reflect_comments_changes: 1 } });  

        // Replace content with filter HTML(without HTML tags) which we get from AJAX response. Github issue: #491. @author: Rishi Shah @since: 3.5
        const sanitizedThreadFromServer = data?.arr?.thread;
        if (sanitizedThreadFromServer) {
          const lastLength = arr.length - 1;
          if (lastLength >= 0 && arr[lastLength]) {
            arr[lastLength].thread = sanitizedThreadFromServer;
          }
        }

        const cacheKey = `${CurrentPostID}-${metaId}`;
        const fetchedCommentCache = select('mdstore').getFetchedCommentCache();
        // check iif the comment is in the cache
        if (fetchedCommentCache[cacheKey]) {
          delete fetchedCommentCache[cacheKey]; // Remove the specific entry
          wp.data.dispatch('mdstore').setFetchedCommentCache(fetchedCommentCache); // Dispatch the updated comment cache
        } 

        // Set the state.
        _this.setState({
          comments: arr,
          newcommentText: "",
          mediaId: "",
          mediaName: "",
          mediaUrl: "",
        });

      // Update comment data store to display in activities without refresh.
      const threadsGlobalData = select("mdstore").getAllCommentCount();
      if (threadsGlobalData?.length !== undefined) {
          arr[0].elID = metaId.replace('_', '');
          threadsGlobalData?.push(...arr);
          dispatch("mdstore").setAllCommentCount(threadsGlobalData);
      }  

        var getundoData = select('mdstore').getundoData();
        var tempArray = [];
        var arrObj = Object.assign({}, arr[0]);
        let obj;

        if( null !== getundoData ) {
            obj = { id: datatext, data: arrObj };
            getundoData.push(obj);
            tempArray = getundoData;
        } else {
            obj = { id: datatext, data: arrObj };
            tempArray.push(obj);
        }
        dispatch('mdstore').setundoData(tempArray);

        undoRedoFun(_this); //phpcs:ignore


        // Flushing the text from the textarea
        document.getElementById(currentTextID).innerHTML = "";
        document.getElementById(currentTextID).focus();
        var elementThumbFile = document.getElementById("cf_thumb_file");
        if (elementThumbFile) {
            elementThumbFile.innerHTML = "";
        }
        // Remove assign checkbox
           document.querySelectorAll(".cf-assign-to").forEach(el => el.remove());
        })
        .catch((err) => {
          console.error("Multicollab add comment failed:", err);
          const shareContainer = document.querySelector(`#${el} .shareCommentContainer`);
          if (shareContainer) {
            shareContainer.classList.remove("loading");
          }
          showNotice(
            __("Something went wrong while saving your comment. Please try again.", "commenting-feature")
          );
        });
        const cfPostStatus = select('core/editor').getCurrentPost().status;
        if (cfPostStatus === 'publish') {
          dispatch('core/editor').savePost();
        } else {
          dispatch('core/editor').autosave();
        }
    } else {
      if (event.currentTarget.classList.contains("btn-disabled")) {
        return false;
    }
    showNotice( __(
      "Please add some comment.",
      "commenting-feature"
    ));
    }
  }

  displayComments(text, i) {
    const { lastVal, onChanged, selectedText } = this.props;
    let username,
      userRole,
      postedTime,
      postedComment,
      profileURL,
      userID,
      status,
      cTimestamp,
      editedDraft,
      updatedTime,
      blockType,
      assignedText,
      editedTimestamp,
      attachmentText;
    Object.keys(text).map((i) => {
      if ("userName" === i) {
        username = text[i];
      } else if ("userRole" === i) {
        userRole = text[i];
      } else if ("dtTime" === i) {
        postedTime = text[i];
      } else if ("thread" === i) {
        postedComment = text[i];
      } else if ("profileURL" === i) {
        profileURL = text[i];
      } else if ("userData" === i) {
        userID = parseInt(text[i], 10);
      } else if ("status" === i) {
        status = text[i];
      } else if ("timestamp" === i) {
        cTimestamp = text[i];
      } else if ("editedDraft" === i) {
        editedDraft = text[i];
      } else if ("updatedTime" === i) {
        updatedTime = text[i].toString();
      } else if ("blockType" === i) {
        blockType = text[i];
      } else if ("assignedText" === i) {
        assignedText = text[i];
      } else if ("editedTimestamp" === i) {
        editedTimestamp = text[i];
      } else if ("attachmentText" === i) {
        attachmentText = text[i];
      }
    });

    // Translation Added for Board Assigned and Reassigned to Text - coded by meet
    let translatedAssignedText = assignedText;
    let splitedUsername;
    if (translatedAssignedText?.includes("Assigned to You")) {
      translatedAssignedText = wp.i18n.__(
        "Assigned to You",
        "commenting-feature"
      );
    } else if (translatedAssignedText?.includes("Reassigned to You")) {
      translatedAssignedText = wp.i18n.__(
        "Reassigned to You",
        "commenting-feature"
      );
    } else if (translatedAssignedText?.includes("Assigned to")) {
      splitedUsername = translatedAssignedText.split("Assigned to");
      translatedAssignedText = sprintf(
        __("Assigned to %s", "commenting-feature"),
        splitedUsername[1]
      );
    } else if (translatedAssignedText?.includes("Reassigned to ")) {
      splitedUsername = translatedAssignedText.split("Reassigned to");
      translatedAssignedText = sprintf(
        __("Reassigned to %s", "commenting-feature"),
        splitedUsername[1]
      );
    }
    assignedText = translatedAssignedText;

    //Multiedit change for matching roles to sidebar collaborator list
    const currentPost = select("core/editor").getCurrentPost();
    const postAuthor = currentPost?.author;
    if (postAuthor === userID) {
      userRole = "Owner";
    }

    return (
      <Comment
        key={i}
        index={i}
        removeCommentFromBoard={this.removeComment}
        updateCommentFromBoard={this.updateComment}
        removeAttachmentFromBoard={this.removeAttachment}
        userName={username}
        userRole={userRole}
        dateTime={postedTime}
        profileURL={profileURL}
        userID={userID}
        status={status}
        lastVal={lastVal}
        onChanged={onChanged}
        selectedText={selectedText}
        timestamp={cTimestamp}
        editedDraft={editedDraft}
        editedTime={updatedTime}
        editedTimestamp={editedTimestamp && editedTimestamp.toString()}
        blockType={blockType}
        assignedText={assignedText}
        attachmentText={attachmentText}
        showAvatars={localStorage.getItem("showAvatars")}
      >
        {(postedComment = postedComment ? postedComment : text)}
      </Comment>
    );
  }

 /**
   * Cancels the current comment being edited or created.
   * This function performs the following actions:
   * - Disables the suggestion mode if it was enabled
   * - Removes the comment-related elements from the DOM
   * - Resets the state of the component
   * - Dispatches events to update the editor layout and show/hide comments
   * - Removes any active classes from the activity center
   * - Re-enables the suggestion mode if it was previously enabled
   */
  
  cancelComment() {

    const { datatext, onChanged, lastVal } = this.props;

    const iframe = cfGetIframe();
    const iframeDocument = iframe ? iframe.contentWindow.document : null;
    
    let element;
    if(iframeDocument){
      element = iframeDocument.querySelector(`[datatext="${datatext}"]`);
    }else{
      element = document.querySelector(`[datatext="${datatext}"]`);
    }
    const parentElement = element.closest('[data-block]');
    const blockType = element?.getAttribute("data-type");
    const blockTypes = parentElement?.getAttribute('data-type');
    let clientId = parentElement?.getAttribute('data-block');
    const selectedBlock = select('core/block-editor').getSelectedBlock();
    if (!clientId) {
        clientId = selectedBlock?.clientId;
    }
    const blockAttributes = select('core/block-editor').getBlockAttributes(clientId);
    const prefixAcf = 'acf/';
    const blockId = element?.getAttribute("data-block");
    const name = "multidots/comment";


    if (document.querySelectorAll(`#${datatext} .boardTop .commentContainer`).length === 0) {

      if (blockType !== undefined && blockType !== null) {
          element?.classList.remove("commentIcon");
          dispatch("mdstore").setIsActive(false);
          dispatch("core/block-editor").updateBlock(blockId, {
              attributes: {
                  datatext: "",
              },
          });
      } else if (blockTypes?.startsWith(prefixAcf) && blockTypes !== undefined && blockType !== null) {
          removeAcfTag(blockAttributes, clientId, datatext);
          dispatch('mdstore').setIsActive(false);
      } else {
          if (lastVal) {
            onChanged(removeFormat(lastVal, name));
          }
      }

      document.getElementById(datatext)?.remove();
      const event = new Event("editorLayoutUpdate");
      document.dispatchEvent(event);
    }

    // Reset Comments Float
    setTimeout(() => {
        document.getElementById("cf-comment-board-wrapper")?.classList.remove("cf-unset-all");
        document.querySelectorAll("#cf-comment-board-wrapper .cls-board-outer").forEach(el => el.classList.remove("focus", "is-open"));
        document.querySelectorAll("#cf-comment-board-wrapper .cls-board-outer").forEach(el => el.removeAttribute("style"));
        document.querySelectorAll("#cf-comment-board-wrapper .cls-board-outer .shareCommentContainer").forEach(el => el.removeAttribute("style"));
        document.querySelectorAll("#cf-comment-board-wrapper .comment-delete-overlay").forEach(el => el.classList.remove("show"));  
        document.querySelectorAll("#cf-comment-board-wrapper .cls-board-outer .buttons-wrapper").forEach(el => el.classList.remove("active"));

        if(iframeDocument){
          iframeDocument.querySelectorAll(".cf-icon__addBlocks, .cf-icon__removeBlocks").forEach(el => el.classList.remove("focus"));
          iframeDocument.querySelectorAll(".cf-icon-wholeblock__comment").forEach(el => {
              el.classList.remove("focus");
              el.classList.remove("is-selected");
          });
          iframeDocument.querySelectorAll(".cf-onwhole-block__comment").forEach(el => el.classList.remove("focus"));
          iframeDocument.querySelectorAll("[data-rich-text-format-boundary]").forEach(el => el.removeAttribute("data-rich-text-format-boundary"));
          iframeDocument.querySelectorAll('.cf-assign-to').forEach(el => el.remove());
          iframeDocument.querySelectorAll(".commentIcon").forEach(el => el.classList.remove("is-selected"));
        }else{
          document.querySelectorAll(".cf-icon__addBlocks, .cf-icon__removeBlocks").forEach(el => el.classList.remove("focus"));
          document.querySelectorAll(".cf-icon-wholeblock__comment").forEach(el => {
              el.classList.remove("focus");
              el.classList.remove("is-selected");
          });
          document.querySelectorAll(".cf-onwhole-block__comment").forEach(el => el.classList.remove("focus"));
          document.querySelectorAll("[data-rich-text-format-boundary]").forEach(el => el.removeAttribute("data-rich-text-format-boundary"));
          document.querySelectorAll('.cf-assign-to').forEach(el => el.remove());
          document.querySelectorAll(".commentIcon").forEach(el => el.classList.remove("is-selected"));
          
        }

          // Clear the inner HTML of the specified text area
          const txtElement = document.getElementById("txt" + datatext);
          if (txtElement) {
              txtElement.innerHTML = "";
          }

          // Clear the content of #cf_thumb_file
          const thumbFileElement = document.getElementById("cf_thumb_file");
          if (thumbFileElement) {
              thumbFileElement.innerHTML = "";
          }
          this.setState({
              newcommentText: "",
              mediaId: "",
              mediaName: "",
              mediaUrl: "",
          });

          const showHideCommentsEvent = new Event("showHideComments");
          document.dispatchEvent(showHideCommentsEvent);

          // Removing the active class from activity center on cancel
          document.querySelectorAll(".js-activity-centre .user-data-row").forEach(el => el.classList.remove("is-active"));
      }, 200);

    const boardIdLength = select('mdstore').getBoardIds()?.length;
    if(boardIdLength == 0){
      const sidebarName = select('core/edit-post').getActiveGeneralSidebarName();
        if (sidebarName === 'edit-post/cf-collab-sidebar') {
            dispatch('core/edit-post').closeGeneralSidebar();
        }
    }

  }


  deleteAttachment() {
    this.setState({
      attachmentText: "",
      mediaId: "",
      mediaName: "",
      mediaUrl: "",
    });
    const thumbFileElement = document.getElementById("cf_thumb_file");
    if (thumbFileElement) {
        thumbFileElement.innerHTML = "";
    }
  }
  

  componentDidMount() {
    let txtselectedText;
    let metaselectedText;
    if (this.props.freshBoard) {
      const datatext = this.props.datatext;
  
      setTimeout(function () {
        const textElement = document.getElementById("txt" + datatext);
        if (textElement) {
            textElement.focus();
        }
      }, 500);
    }
    const currentPostID = select("core/editor").getCurrentPostId(); 
    const currentUserID = select("core").getCurrentUser()?.id ?? null;
     
    txtselectedText = "txt" + this.props.datatext;
    metaselectedText = "_" + this.props.datatext;
    // Optional: Add a check to make sure required props are available
    if (1 !== this.props.freshBoard) {
      if (currentPostID && metaselectedText ) {
        this.fetchCommentData(currentPostID, metaselectedText, currentUserID);
      }
    }
  }

  render() {
    const { datatext, setAttributes, attributes } = this.props;
    const buttonText =
      1 === this.hasComments
        ? __("Reply", "commenting-feature")
        : __("Comment", "commenting-feature");
    const tooltipText =
      1 === this.hasComments
        ? __("Reply to this comment", "commenting-feature")
        : __("Post Comment", "commenting-feature");
    const assignedTo = this.assignedTo;
    const assigneeLabel =
      assignedTo &&
      (assignedTo.display_name || assignedTo.username || "").trim();
    var placeHolder =
      1 === this.hasComments || undefined === this.hasComments
        ? __(
            "Reply or add others with @",
            "commenting-feature"
          )
        : __(
            "Comment or add others with @",
            "commenting-feature"
          );
    if (this.props.freshBoard) {
      placeHolder = __(
        "Comment or add others with @",
        "commenting-feature"
      );
    }
    let commentCount = this.state.comments.length;
    let displayValue = "none";
    if (commentCount > getCommentsLimit()) {
      displayValue = "block";
    }
    var newText = this.state.newcommentText;
    newText = validateCommentReplyText(newText);

    let buttonClass = "";
    if (newText === "") {
      buttonClass = "btn-disabled";
    }
    return (
      <div
        className={`board  ${
          undefined === this.hasComments &&
          this.currentUserProfile &&
          "fresh-board"
        }`}
      >
        {assignedTo != null && (
          <div
            className="cf-board-assigned-to"
            data-user-id={assignedTo.ID ?? ""}
            data-user-email={assignedTo.user_email ?? assignedTo.email ?? ""}
          >
            <div className="assigned-user-details">
              <div className="user-avatar">
                <img src={assignedTo.avatar ?? ""} alt={assigneeLabel} />
              </div>
              <div className="user-info">
                <span className="badge">
                  {__("Assigned to", "commenting-feature")}
                </span>
                <p className="display-name">
                  {assigneeLabel
                    ? __(
                        assigneeLabel.charAt(0).toUpperCase() +
                          assigneeLabel.slice(1),
                        "commenting-feature"
                      )
                    : __(
                        "Unknown User",
                        "commenting-feature"
                      )}
                </p>
              </div>
            </div>
          </div>
        )}
        <div className="boardTop">
          {this.state.comments &&
            this.state.comments.map((item, index) => {
              return this.displayComments(item, index);
            })}
          <div className="show-all-comments" style={{ display: displayValue }}>
            {sprintf(__("Show all %d replies"), commentCount - 1)}
          </div>
        </div>
        {undefined === this.hasComments && this.currentUserProfile && (
          <div className="commentContainer">
            <div className="commentInnerContainer">
              <div className="comment-header">
                <div className="comment-details">
                  <div className="avatar">
                    <img src={this.currentUserProfile} alt="avatar" />
                  </div>
                  <div className="commenter-name-time">
                    <div className="commenter-name">
                    {this.currentUserName.charAt(0).toUpperCase() + this.currentUserName.slice(1)}</div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        )}

        <div className="shareCommentContainer">
          <div className="cf-share-comment-wrapper js-cf-share-comment-wrapper">
            <ContentEditable
              innerRef={this.contentEditable}
              html={this.state.newcommentText}
              disabled={false}
              onChange={(e) =>
                this.setState({ newcommentText: e.target.value })
              }
              id={"txt" + datatext}
              className="cf-share-comment js-cf-share-comment"
              placeholder={placeHolder}
            />
            <div className="cf-commentboard-attach-wrap">
              {this.state.mediaId != undefined && (
                <div id="cf_thumb_file">
                  <a href={this.state.mediaUrl} target="_blank">
                    {this.state.mediaName}
                  </a>
                </div>
              )}
              <div className="btn-wrapper">
                <button
                  onClick={this.addNewComment}
                  className={`btn btn-success ${buttonClass}`}
                >
                  {buttonText}
                  <span className="tooltip">{tooltipText}</span>
                </button>
                <button onClick={this.cancelComment} className="btn btn-cancel">
                  {__("Cancel", "commenting-feature")}{" "}
                  <span className="tooltip">
                    {__(
                      "Discard Comment",
                      "commenting-feature"
                    )}
                  </span>
                </button>
              </div>
            </div>
          </div>
        </div>
      </div>
    );
  }
}

// Typecheck.
Board.propTypes = {
  lastVal: PropTypes.object,
  datatext: PropTypes.string,
  onChanged: PropTypes.func,
  selectedText: PropTypes.string,
  commentedOnText: PropTypes.string,
  freshBoard: PropTypes.number,
  onLoadFetch: PropTypes.number,
};
