// import libWrapperShared from "./libWrapperShared.js";

export default class ChatMerge {
  static get _enabled() {
    return true;
  }
  static get _epoch() {
    return 10;
  }
  static get _allowRolls() {
    return "rolls";
  }
  static get _separateWithBorder() {
    return false;
  }
  static get _showHover() {
    return false;
  }
  static get _showHeader() {
    return false;
  }

  static init() {
    // libWrapperShared.register("ChatLog.prototype.deleteMessage", this._deleteMessage.bind(this));
    Hooks.on("renderChatMessage", this._renderChatMessage);
    Hooks.on("deleteChatMessage", this.deleteMessage);
  }

  static ready() {
    const style = document.querySelector(":root").style;
    // style.setProperty("--dfce-cm-separation", this._separateWithBorder ? "" : "0");
    // this._showHover
    //   ? style.removeProperty("--dfce-cm-hover-shadow")
    //   : style.setProperty("--dfce-cm-hover-shadow", "0px");
    // style.setProperty("--dfce-cm-header", this._showHeader ? "" : "none");
    // if (game.user.isGM) {
    //   style.setProperty("--dfce-cm-header-delete", this._showHeader ? "" : "0");
    //   style.setProperty("--dfce-cm-header-delete-pad", this._showHeader ? "" : "16px");
    // }
    this._processAllMessage(ui.chat.element);
    Hooks.on("renderChatLog", (_, html) => this._processAllMessage(html));
  }

  static deleteMessage(message, flags) {
    if (flags.deleteAll === true) return;
    const messageId = message._id;
    const element = document.querySelector(`li[data-message-id="${messageId}"`);
    // If we were a TOP
    if (element?.classList?.contains("dfce-cm-top")) {
      element.classList.remove("dfce-cm-top");
      // If the next element was a middle, make it a top
      if (element.nextElementSibling.classList.contains("dfce-cm-middle")) {
        element.nextElementSibling.classList.remove("dfce-cm-middle");
        element.nextElementSibling.classList.add("dfce-cm-top");
      }
      // Otherwise, it was a bottom and should now become a normal message again
      else element.nextElementSibling.classList.remove("dfce-cm-bottom");
    }
    // If we were a BOTTOM
    else if (element?.classList?.contains("dfce-cm-bottom")) {
      element.classList.remove("dfce-cm-bottom");
      // If the previous element was a middle, make it a bottom
      if (element.previousElementSibling.classList.contains("dfce-cm-middle")) {
        element.previousElementSibling.classList.remove("dfce-cm-middle");
        element.previousElementSibling.classList.add("dfce-cm-bottom");
      }
      // Otherwise, it was a top and should now become a normal message again
      else element.previousElementSibling.classList.remove("dfce-cm-top");
    }
    // If we were a MIDDLE, let the above and below snug and they'll be fine
    else if (element?.classList?.contains("dfce-cm-middle")) element.classList.remove("dfce-cm-middle");
  }

  // static _deleteMessage(wrapper, messageId, { deleteAll = false } = {}) {
  //   // Ignore the Delete All process. Everything is being obliterated, who cares about the styling
  //   if (!deleteAll && this._enabled) {
  //     const element = document.querySelector(`li[data-message-id="${messageId}"`);
  //     // If we were a TOP
  //     if (element?.classList?.contains("dfce-cm-top")) {
  //       element.classList.remove("dfce-cm-top");
  //       // If the next element was a middle, make it a top
  //       if (element.nextElementSibling.classList.contains("dfce-cm-middle")) {
  //         element.nextElementSibling.classList.remove("dfce-cm-middle");
  //         element.nextElementSibling.classList.add("dfce-cm-top");
  //       }
  //       // Otherwise, it was a bottom and should now become a normal message again
  //       else element.nextElementSibling.classList.remove("dfce-cm-bottom");
  //     }
  //     // If we were a BOTTOM
  //     else if (element?.classList?.contains("dfce-cm-bottom")) {
  //       element.classList.remove("dfce-cm-bottom");
  //       // If the previous element was a middle, make it a bottom
  //       if (element.previousElementSibling.classList.contains("dfce-cm-middle")) {
  //         element.previousElementSibling.classList.remove("dfce-cm-middle");
  //         element.previousElementSibling.classList.add("dfce-cm-bottom");
  //       }
  //       // Otherwise, it was a top and should now become a normal message again
  //       else element.previousElementSibling.classList.remove("dfce-cm-top");
  //     }
  //     // If we were a MIDDLE, let the above and below snug and they'll be fine
  //     else if (element?.classList?.contains("dfce-cm-middle")) element.classList.remove("dfce-cm-middle");
  //   }
  //   return wrapper(messageId, { deleteAll });
  // }

  static _processAllMessage(element) {
    element = element ?? $(document.body);
    // Remove the old CSS class designations
    element.find(".dfce-cm-top").removeClass("dfce-cm-top");
    element.find(".dfce-cm-middle").removeClass("dfce-cm-middle");
    element.find(".dfce-cm-bottom").removeClass("dfce-cm-bottom");
    // If we are disabled, return
    if (!ChatMerge._enabled) return;
    // Collect all rendered chat messages
    const messages = element.find("li.chat-message");
    // Return if there are no messages rendered
    if (messages.length === 0) return;

    // Process each message after the first
    for (let c = 1; c < messages.length; c++) {
      // Update styling of the chat messages
      this._styleChatMessages(
        game.messages.get(messages[c].getAttribute("data-message-id")),
        messages[c],
        game.messages.get(messages[c - 1].getAttribute("data-message-id")),
        messages[c - 1]
      );
    }
  }

  static _renderChatMessage(message, html, _cmd) {
    if (!ChatMerge._enabled) return;
    // Find the most recent message in the chat log
    const partnerElem = $(`li.chat-message`).last()[0];
    // If there is no message, return
    if (partnerElem === null || partnerElem === undefined) return;
    // get the ChatMessage document associated with the html
    const partner = game.messages.get(partnerElem.getAttribute("data-message-id"));
    if (!message || !partner) return;
    // Update styling of the chat messages
    ChatMerge._styleChatMessages(message, html[0], partner, partnerElem);
  }

  static _inTimeFrame(current, previous) {
    return current > previous && current - previous < this._epoch * 1000;
  }

  static _isValidMessage(current, previous) {
    const rolls = this._allowRolls;
    // const splitSpeaker = SETTINGS.get < boolean > this.PREF_SPLIT_SPEAKER;
    const splitSpeaker = true;
    let userCompare = false;
    const currData = current ?? current;
    const prevData = previous ?? previous;
    if (splitSpeaker) {
      // this is a bit complex, basically we want to group by actors, but if you're not using an actor, group by user instead
      userCompare =
        // If actors are equal and NOT null
        (currData.speaker.actor === prevData.speaker.actor && !!currData.speaker.actor) || // If BOTH actors are null and users are equal
        (!currData.speaker.actor && !prevData.speaker.actor && currData.user === prevData.user);
    } else {
      // If we are not splitting by speaker, just do the simple option of comparing the users
      userCompare = currData.user === prevData.user;
    }
    return (
      userCompare &&
      this._inTimeFrame(currData.timestamp, prevData.timestamp) &&
      // Check for merging with roll types
      (rolls === "all" ||
        (rolls === "rolls" && current.isRoll === previous.isRoll) ||
        (rolls === "none" && !current.isRoll && !previous.isRoll))
    );
  }

  static _styleChatMessages(curr, currElem, prev, prevElem) {
    if (!ChatMerge._isValidMessage(curr, prev)) return;
    if (prevElem.classList.contains("dfce-cm-bottom")) {
      prevElem.classList.remove("dfce-cm-bottom");
      prevElem.classList.add("dfce-cm-middle");
    } else prevElem.classList.add("dfce-cm-top");
    currElem.classList.add("dfce-cm-bottom");
  }
}
