let main_parent = document.getElementById('chat-tab').parentNode;
let extensions = document.getElementById('extensions');

main_parent.childNodes[0].classList.add("header_bar");
main_parent.style = "padding: 0; margin: 0";
main_parent.parentNode.style = "gap: 0";
main_parent.parentNode.parentNode.style = "padding: 0";

document.querySelector('.header_bar').addEventListener('click', function(event) {
    if (event.target.tagName === 'BUTTON') {
        const buttonText = event.target.textContent.trim();

        let chat_visible = (buttonText == 'Chat');
        let default_visible = (buttonText == 'Default');
        let notebook_visible = (buttonText == 'Notebook');

        // Check if one of the generation tabs is visible
        if (chat_visible || notebook_visible || default_visible) {
            extensions.style.display = 'flex';
            if (chat_visible) {
                extensions.style.maxWidth = "880px";
                extensions.style.padding = "0px";
            } else {
                extensions.style.maxWidth = "none";
                extensions.style.padding = "15px";
            }
        } else {
            extensions.style.display = 'none';
        }
    }
});

//------------------------------------------------
// Keyboard shortcuts
//------------------------------------------------
document.addEventListener("keydown", function(event) {

  // Stop generation on Esc pressed
  if (event.key === "Escape") {
    // Find the element with id 'stop' and click it
    var stopButton = document.getElementById("stop");
    if (stopButton) {
      stopButton.click();
    }
  }

  // Show chat controls on Ctrl + S
  else if (event.ctrlKey && event.key == "s") {
    event.preventDefault();

    var showControlsElement = document.getElementById('show-controls');
    if (showControlsElement && showControlsElement.childNodes.length >= 4) {
      showControlsElement.childNodes[3].click();

      var arr = document.getElementById('chat-input').childNodes[2].childNodes;
      arr[arr.length - 1].focus();
    }
  }

  // Regenerate on Ctrl + Enter
  else if (event.ctrlKey && event.key === 'Enter') {
    event.preventDefault();
    document.getElementById('Regenerate').click();
  }

  // Continue on Alt + Enter
  else if (event.altKey && event.key === 'Enter') {
    event.preventDefault();
    document.getElementById('Continue').click();
  }

  // Remove last on Ctrl + Shift + Backspace
  else if (event.ctrlKey && event.shiftKey && event.key === 'Backspace') {
    event.preventDefault();
    document.getElementById('Remove-last').click();
  }

  // Copy last on Ctrl + Shift + K
  else if (event.ctrlKey && event.shiftKey && event.key === 'K') {
    event.preventDefault();
    document.getElementById('Copy-last').click();
  }

  // Replace last on Ctrl + Shift + L
  else if (event.ctrlKey && event.shiftKey && event.key === 'L') {
    event.preventDefault();
    document.getElementById('Replace-last').click();
  }

  // Impersonate on Ctrl + Shift + M
  else if (event.ctrlKey && event.shiftKey && event.key === 'M') {
    event.preventDefault();
    document.getElementById('Impersonate').click();
  }

});

//------------------------------------------------
// Position the chat typing dots
//------------------------------------------------
typing = document.getElementById('typing-container');
typingParent = typing.parentNode;
typingSibling = typing.previousElementSibling;
typingSibling.insertBefore(typing, typingSibling.childNodes[2]);

//------------------------------------------------
// Chat scrolling
//------------------------------------------------
const targetElement = document.getElementById('chat').parentNode.parentNode.parentNode;
targetElement.classList.add('pretty_scrollbar');
targetElement.classList.add('chat-parent');
let isScrolled = false;

targetElement.addEventListener('scroll', function() {
  let diff = targetElement.scrollHeight - targetElement.clientHeight;
  if(Math.abs(targetElement.scrollTop - diff) <= 1 || diff == 0) {
    isScrolled = false;
  } else {
    isScrolled = true;
  }
});

// Create a MutationObserver instance
const observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    if(!isScrolled) {
      targetElement.scrollTop = targetElement.scrollHeight;
    }

    const firstChild = targetElement.children[0];
    if (firstChild.classList.contains('generating')) {
      typing.parentNode.classList.add('visible-dots');
      document.getElementById('stop').style.display = 'flex';
      document.getElementById('Generate').style.display = 'none';
    } else {
      typing.parentNode.classList.remove('visible-dots');
      document.getElementById('stop').style.display = 'none';
      document.getElementById('Generate').style.display = 'flex';
    }

  });
});

// Configure the observer to watch for changes in the subtree and attributes
const config = {
  childList: true,
  subtree: true,
  characterData: true,
  attributeOldValue: true,
  characterDataOldValue: true
};

// Start observing the target element
observer.observe(targetElement, config);

//------------------------------------------------
// Notebook box scrolling
//------------------------------------------------
const notebookElement = document.querySelector('#textbox-notebook textarea');
let notebookScrolled = false;

notebookElement.addEventListener('scroll', function() {
  let diff = notebookElement.scrollHeight - notebookElement.clientHeight;
  if(Math.abs(notebookElement.scrollTop - diff) <= 1 || diff == 0) {
    notebookScrolled = false;
  } else {
    notebookScrolled = true;
  }
});

const notebookObserver = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    if(!notebookScrolled) {
      notebookElement.scrollTop = notebookElement.scrollHeight;
    }
  });
});

notebookObserver.observe(notebookElement.parentNode.parentNode.parentNode, config);

//------------------------------------------------
// Default box scrolling
//------------------------------------------------
const defaultElement = document.querySelector('#textbox-default textarea');
let defaultScrolled = false;

defaultElement.addEventListener('scroll', function() {
  let diff = defaultElement.scrollHeight - defaultElement.clientHeight;
  if(Math.abs(defaultElement.scrollTop - diff) <= 1 || diff == 0) {
    defaultScrolled = false;
  } else {
    defaultScrolled = true;
  }
});

const defaultObserver = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    if(!defaultScrolled) {
      defaultElement.scrollTop = defaultElement.scrollHeight;
    }
  });
});

defaultObserver.observe(defaultElement.parentNode.parentNode.parentNode, config);

//------------------------------------------------
// Add some scrollbars
//------------------------------------------------
const textareaElements = document.querySelectorAll('.add_scrollbar textarea');
for(i = 0; i < textareaElements.length; i++) {
    textareaElements[i].classList.remove('scroll-hide');
    textareaElements[i].classList.add('pretty_scrollbar');
    textareaElements[i].style.resize = "none";
}

//------------------------------------------------
// Improve the looks of the chat input field
//------------------------------------------------
let isOld = document.querySelectorAll('.old-ui').length > 0;

document.getElementById('chat-input').parentNode.style.background = 'transparent';
document.getElementById('chat-input').parentNode.style.border = 'none';
document.getElementById('chat-input').parentElement.parentElement.style.minWidth = 0;

document.getElementById('stop').parentElement.parentElement.style.minWidth = 0;
document.getElementById('stop').parentElement.parentElement.style.display = 'flex';
document.getElementById('stop').parentElement.parentElement.style.flexDirection = 'column-reverse';
document.getElementById('stop').parentElement.parentElement.style.paddingBottom = '3px';
document.getElementById('stop').parentElement.parentElement.parentElement.style.paddingBottom = isOld ? '0px' : '20px';

document.getElementById('stop').parentElement.parentElement.style.flex = '0 0 auto';

document.getElementById('gr-hover').parentElement.style.minWidth = 0;
document.getElementById('gr-hover').parentElement.style.display = 'flex';
document.getElementById('gr-hover').parentElement.style.flexDirection = 'column-reverse';
document.getElementById('gr-hover').parentElement.style.flex = '0';
document.getElementById('gr-hover').parentElement.style.paddingRight = '20px';
document.getElementById('gr-hover').parentElement.style.paddingBottom = '3px';

//------------------------------------------------
// Remove some backgrounds
//------------------------------------------------
const noBackgroundelements = document.querySelectorAll('.no-background');
for(i = 0; i < noBackgroundelements.length; i++) {
    noBackgroundelements[i].parentNode.style.border = 'none';
    noBackgroundelements[i].parentNode.parentNode.parentNode.style.alignItems = 'center';
}

//------------------------------------------------
// Create the hover menu in the chat tab
// The show/hide events were adapted from:
// https://github.com/SillyTavern/SillyTavern/blob/6c8bd06308c69d51e2eb174541792a870a83d2d6/public/script.js
//------------------------------------------------
var buttonsInChat = document.querySelectorAll("#chat-tab #chat-buttons:not(.old-ui) button");
var button = document.getElementById('hover-element-button');
var menu = document.getElementById('hover-menu');

function showMenu() {
    menu.style.display = 'flex'; // Show the menu
}

function hideMenu() {
    menu.style.display = 'none'; // Hide the menu
}

if (buttonsInChat.length > 0) {
    for (let i = buttonsInChat.length - 1; i >= 0; i--) {
        const thisButton = buttonsInChat[i];
        menu.appendChild(thisButton);

        if(i != 8) {
            thisButton.addEventListener("click", () => {
                hideMenu();
            });
        }

        const buttonText = thisButton.textContent;
        const matches = buttonText.match(/(\(.*?\))/);

        if (matches && matches.length > 1) {
            // Apply the transparent-substring class to the matched substring
            const substring = matches[1];
            const newText = buttonText.replace(substring, `&nbsp;<span class="transparent-substring">${substring}</span>`);
            thisButton.innerHTML = newText;
        }
    }
} else {
    buttonsInChat = document.querySelectorAll("#chat-tab #chat-buttons.old-ui button");
    console.log(buttonsInChat);
    for (let i = 0; i < buttonsInChat.length; i++) {
        buttonsInChat[i].textContent = buttonsInChat[i].textContent.replace(/ \(.*?\)/, '');
    }
    document.getElementById('gr-hover').parentElement.style.display = 'none';
}

function isMouseOverButtonOrMenu() {
    return menu.matches(':hover') || button.matches(':hover');
}

button.addEventListener('mouseenter', function () {
    showMenu();
});

button.addEventListener('click', function () {
    showMenu();
});

// Add event listener for mouseleave on the button
button.addEventListener('mouseleave', function () {
    // Delay to prevent menu hiding when the mouse leaves the button into the menu
    setTimeout(function () {
        if (!isMouseOverButtonOrMenu()) {
            hideMenu();
        }
    }, 100);
});

// Add event listener for mouseleave on the menu
menu.addEventListener('mouseleave', function () {
    // Delay to prevent menu hide when the mouse leaves the menu into the button
    setTimeout(function () {
        if (!isMouseOverButtonOrMenu()) {
            hideMenu();
        }
    }, 100);
});

// Add event listener for click anywhere in the document
document.addEventListener('click', function (event) {
    // Check if the click is outside the button/menu and the menu is visible
    if (!isMouseOverButtonOrMenu() && menu.style.display === 'flex') {
        hideMenu();
    }
});

//------------------------------------------------
// Relocate the "Show controls" checkbox
//------------------------------------------------
var elementToMove = document.getElementById('show-controls');
var parent = elementToMove.parentNode;
for (var i = 0; i < 2; i++) {
  parent = parent.parentNode;
}

parent.insertBefore(elementToMove, parent.firstChild);

//------------------------------------------------
// Make the chat input grow upwards instead of downwards
//------------------------------------------------
document.getElementById('show-controls').parentNode.style.position = 'absolute';
document.getElementById('show-controls').parentNode.style.bottom = '0px';

//------------------------------------------------
// Focus on the chat input
//------------------------------------------------
document.querySelector('#chat-input textarea').focus()