import { addWebUiListener } from "chrome://resources/js/cr.js";
import { loadTimeData } from "chrome://resources/js/load_time_data.js";
window.loadTimeData = loadTimeData;
let next_message_id_ = 100000;
const response_map_ = new Map();
// Avatars
const AVATAR_COUNT = 38;
const AVATAR_SKIP_INDEX = 26; // Unused index

const xmlns = "http://www.w3.org/2000/svg";
const userSVG =
  "M10 20c5.523 0 10-4.477 10-10S15.523 0 10 0 0 4.477 0 10s4.477 10 10 10Zm5.68-4.366A7.976 7.976 0 0 1 10 18c-2.22 0-4.23-.905-5.68-2.366C5.244 13.295 6.96 12 7.93 12h4.142c.97 0 2.686 1.295 3.608 3.634Zm-2.347-8.467a3.333 3.333 0 1 1-6.666 0 3.333 3.333 0 0 1 6.666 0Z";

addWebUiListener("vivaldi-ui-response", resp => {
  const callback = response_map_.get(resp.callbackId);
  if (callback) {
    callback(resp.response);
    response_map_.delete(resp.callbackId);
  }
});

function sendWithResponse(messageId, args, callback) {
  next_message_id_++;
  response_map_.set(next_message_id_, callback);
  chrome.send(messageId, [next_message_id_, args]);
}

function getAvatarUrl(index) {
  return `chrome://theme/IDR_PROFILE_VIVALDI_AVATAR_${index}`;
}

function clearElement(element) {
  while (element.firstChild) {
    element.removeChild(element.firstChild);
  }
}

function showProfiles(refresh = false) {
  const pageTitle = loadTimeData.getString("whoIsUsing");
  const introText = loadTimeData.getString("introText");
  const guestMode = loadTimeData.getString("guestMode");
  const showOnStartup = loadTimeData.getString("onStartup");
  const contextButtonDeleteText = loadTimeData.getString(
    "contextButtonDeleteText",
  );
  const selectAvatarText = loadTimeData.getString("selectCustomAvatar");
  const confirmationText = loadTimeData
    .getString("confirmationText")
    .replace("__1", "$1"); // Preventing grdp form replaces $1 by its own wildcards
  const buttonCancelText = loadTimeData.getString("cancelButtonText");
  const contextButtonEditText = loadTimeData.getString("contextButtonEditText");
  const contextButtonText = loadTimeData.getString("contextButtonText");
  const buttonDeleteProfileText = loadTimeData.getString(
    "contextButtonDeleteLongText",
  );
  const buttonSaveText = loadTimeData.getString("saveButtonText");

  document.title = pageTitle;
  sendWithResponse("getProfilesInfo", {}, response => {
    // Show window-bar only when profile picker is open as modal (not browser tab)
    const windowBar = document.querySelector(".window-bar");
    if (windowBar && response.enableCSD) {
      windowBar.classList.add("visible");
    }

    // Root
    const portal = document.querySelector(".ProfilePicker");
    clearElement(portal);

    // Vivaldi logo
    const logo = document.createElement("img");
    logo.width = 68;
    logo.height = 68;
    logo.className = "logo";
    logo.src = "welcomepage-vivaldi.svg";
    portal.appendChild(logo);

    // Heading
    const h1 = document.createElement("h1");
    h1.innerText = pageTitle;
    portal.appendChild(h1);

    // Intro paragraph
    const intro = document.createElement("p");
    intro.innerText = introText;
    portal.appendChild(intro);

    // Selected profile reference
    let selectedProfile = null;

    // ----------------------------------------
    // Profile button list
    // ----------------------------------------
    const wrapper = document.createElement("div");
    wrapper.className = "ProfilePicker-List";

    response.profiles
      .sort((a, b) => a.name.localeCompare(b.name))
      .forEach((profile, index) => {
        // Profile button wrapper
        const button = document.createElement("button");
        button.className = "ProfilePicker-Profile";
        button.onclick = () => {
          const openDialogs = document.querySelectorAll("[open]");
          if (openDialogs.length) {
            return;
          }
          sendWithResponse("pickProfile", { path: profile.path }, () => {});
        };
        button.oncontextmenu = event => {
          event.preventDefault();
        };

        // Editable name input
        const name = document.createElement("input");
        name.type = "text";
        name.className = "ProfilePicker-Name";
        name.value = profile.name || profile.path.split("/").at(-1);
        name.onclick = event => {
          event.preventDefault();
          event.stopPropagation();
        };
        name.onchange = event => {
          sendWithResponse(
            "modifyProfile",
            {
              name: event.currentTarget.value,
              path: profile.path,
            },
            () => showProfiles(true),
          );
        };

        // Profile avatar icon
        const img = document.createElement("img");
        img.className = "ProfilePicker-Avatar";
        img.src = profile.customAvatar
          ? profile.customAvatar
          : getAvatarUrl(profile.avatarIconIndex);
        img.alt = "";

        // ----------------------------------------
        // Profile button context menu
        // ----------------------------------------
        const profileId = `profile-context-${index}`;
        const menu = document.createElement("ul");
        menu.className = "ProfilePicker-Drop";
        menu.id = profileId;
        menu.role = "menu";

        const closeMenu = function () {
          const openMenu = document.querySelector(".open");
          if (openMenu) {
            openMenu.classList.remove("open");
            openMenu.ariaExpanded = false;
          }
        };

        const openMenu = function () {
          closeMenu();
          menu.classList.add("open");
          contextButton.ariaExpanded = true;
          document.addEventListener("mousedown", function clicked(e) {
            if (e.target.closest("li")) {
              return;
            }
            document.removeEventListener("mousedown", clicked, false);
            closeMenu();
          });
          document.addEventListener("keydown", function keyB(e) {
            if (e.key === "Escape") {
              closeMenu();
              document.removeEventListener("keydown", keyB, false);
              return;
            }
            if (e.key === "ArrowDown") {
              e.preventDefault();
              document.activeElement === menuItem1
                ? menuItem2.focus()
                : menuItem1.focus();
              return;
            }
            if (e.key === "ArrowUp") {
              e.preventDefault();
              document.activeElement === menuItem2
                ? menuItem1.focus()
                : menuItem2.focus();
              return;
            }
          });
        };

        // Context menu buttons
        const contextButton = document.createElement("input");
        contextButton.type = "button";
        contextButton.value = "...";
        contextButton.title = contextButtonText;
        contextButton.className = "ProfilePicker-Menu";
        contextButton.onmousedown = event => {
          event.preventDefault();
          event.stopPropagation();
          openMenu();
        };
        contextButton.onclick = event => {
          event.preventDefault();
          event.stopPropagation();
          if (!menu.classList.contains("open")) {
            openMenu();
          }
        };
        contextButton.ariaExpanded = menu.classList.contains("open");
        contextButton.ariaControls = profileId;
        contextButton.ariaHasPopup = "true";

        const menuItem1 = document.createElement("li");
        menuItem1.role = "menuitem";
        menuItem1.tabIndex = 1;
        menuItem1.innerText = contextButtonEditText;

        function showEditDialog(event) {
          event.stopPropagation();
          event.preventDefault();
          selectedProfile = profile;
          nameInput.value = selectedProfile.name;
          nameInput.placeholder = selectedProfile?.path.split("/").at(-1);
          closeMenu();
          editorDialog.showModal();
        }
        menuItem1.onmouseup = e => e.button === 0 && showEditDialog(e);
        menuItem1.onkeydown = e => {
          if (e.key === " " || e.key === "Enter") {
            showEditDialog(e);
          }
        };

        const menuItem2 = document.createElement("li");
        menuItem2.role = "menuitem";
        menuItem2.tabIndex = 1;
        menuItem2.className =
          response.profiles.length === 1 ? "disabled" : null;
        menuItem2.innerText = contextButtonDeleteText;
        function showDeleteDialog() {
          closeMenu();
          selectedProfile = profile;
          confirmationWrapper.innerText = confirmationText.replace(
            "$1",
            profile.name,
          );
          confirmationDialog.showModal();
        }
        menuItem2.onmouseup = e => {
          e.button === 0 && showDeleteDialog();
        };
        menuItem2.onkeydown = e => {
          if (e.key === " " || e.key === "Enter") {
            showDeleteDialog();
          }
        };

        menu.appendChild(menuItem1);
        menu.appendChild(menuItem2);

        button.appendChild(img);
        button.appendChild(name);
        button.appendChild(contextButton);
        button.appendChild(menu);
        wrapper.appendChild(button);
      });

    portal.appendChild(wrapper);

    // ----------------------------------------
    // Dialog footer controls
    // ----------------------------------------
    const buttonWrapper = document.createElement("div");
    buttonWrapper.className = "ProfilePicker-Controls";

    if (!refresh) {
      // Guest mode button
      const guestButton = document.createElement("button");
      guestButton.onclick = () => {
        sendWithResponse("pickProfile", {}, () => {});
      };
      const userImage = document.createElementNS(xmlns, "svg");
      userImage.setAttributeNS(null, "width", 20);
      userImage.setAttributeNS(null, "height", 20);
      const userImagePath = document.createElementNS(xmlns, "path");
      userImagePath.setAttributeNS(null, "fill", "currentColor");
      userImagePath.setAttributeNS(null, "fill-rule", "evenodd");
      userImagePath.setAttributeNS(null, "d", userSVG);
      userImage.appendChild(userImagePath);
      guestButton.appendChild(userImage);
      const userText = document.createElement("span");
      userText.innerText = guestMode;
      guestButton.appendChild(userText);
      buttonWrapper.appendChild(guestButton);

      // "Show on startup" button
      const startupLabel = document.createElement("label");
      const inputBox = document.createElement("input");
      inputBox.type = "checkbox";
      inputBox.checked = response.showOnStartup;
      inputBox.onchange = () => {
        sendWithResponse(
          "setShowOnStartup",
          { value: inputBox.checked },
          () => {},
        );
      };
      const inputText = document.createElement("span");
      inputText.innerText = showOnStartup;
      startupLabel.appendChild(inputBox);
      startupLabel.appendChild(inputText);
      buttonWrapper.appendChild(startupLabel);
      portal.insertAdjacentElement("afterend", buttonWrapper);
    }

    // ----------------------------------------
    // Profile editor dialog
    // ----------------------------------------
    const editorDialog = document.createElement("dialog");
    editorDialog.className = "ProfilePicker-Dialog";
    // Header
    const editorDialogForm = document.createElement("form");
    editorDialogForm.method = "dialog";
    editorDialogForm.onsubmit = () => {
      sendWithResponse(
        "modifyProfile",
        {
          name: selectedProfile.name,
          avatarIconIndex: selectedProfile.avatarIconIndex,
          path: selectedProfile.path,
        },
        () => showProfiles(true),
      );
    };

    // Profile name, populated from Edit menu
    const nameInput = document.createElement("input");
    nameInput.type = "text";
    nameInput.className = "ProfilePicker-Name";
    nameInput.autoFocus = true;
    nameInput.onchange = event => {
      selectedProfile.name = event.currentTarget.value;
    };
    editorDialogForm.appendChild(nameInput);

    // Avatar button wrapper
    const iconWrapper = document.createElement("div");
    iconWrapper.className = "avatarlist";

    // Custom image selection and choice
    const customImageButton = document.createElement("input");
    customImageButton.type = "button";
    customImageButton.title = selectAvatarText;
    customImageButton.className = "avatarbox avatarbox-custom";
    customImageButton.value = "﹢";
    customImageButton.onclick = event => {
      sendWithResponse("chooseFile", {}, (resp, status) => {
        if (resp.error) {
          // In case of error, a string one of those:
          // open_failed read_failed too_big not_image
          // if (resp.error == "not_image") { alert("selected file is not an image"); }
          console.log(
            "The file is not usable for the icon. Reason:",
            resp.error,
          );
          showProfiles(true);
          return;
        }
        sendWithResponse(
          "modifyProfile",
          {
            name: selectedProfile.name,
            avatarIconPath: resp.file,
            path: selectedProfile.path,
          },
          (resp, status) => showProfiles(true),
        );
      });
    };
    iconWrapper.appendChild(customImageButton);

    function cleanSelectedAvatar() {
      const prevSelected = portal.querySelectorAll(".selected");
      prevSelected.forEach(element => element.classList.remove("selected"));
    }

    // Avatar icon list
    for (let index = 0; index < AVATAR_COUNT; index++) {
      if (index === AVATAR_SKIP_INDEX) {
        continue;
      }
      const imageButton = document.createElement("button");
      imageButton.type = "button";
      imageButton.className = "avatarbox";
      const imageDiv = document.createElement("div");
      imageDiv.className = "avatarbox-image";
      imageDiv.title =
        (index >= 28 ? "Animal" : index >= 18 ? "Monster" : "Landscape") +
        " " +
        (index + 1);
      imageDiv.style.backgroundImage = "url(" + getAvatarUrl(index) + ")";
      imageButton.appendChild(imageDiv);
      iconWrapper.appendChild(imageButton);

      const img_index = index;
      imageButton.onkeydown = event => {
        if (event.key === "Enter") {
          imageButton.click(event);
          editorDialogForm.requestSubmit();
        }
      };
      imageButton.onclick = event => {
        cleanSelectedAvatar();
        event.currentTarget.classList.add("selected");
        selectedProfile.avatarIconIndex = img_index;
      };
    }
    editorDialogForm.appendChild(iconWrapper);

    // Profile editor buttons
    const editorButtons = document.createElement("div");
    editorButtons.className = "ProfilePicker-Buttons";
    const buttonSave = document.createElement("input");
    buttonSave.type = "submit";
    buttonSave.value = buttonSaveText;
    editorButtons.appendChild(buttonSave);
    const buttonCancel = document.createElement("input");
    buttonCancel.type = "button";
    buttonCancel.value = buttonCancelText;
    buttonCancel.onclick = event => {
      editorDialog.close();
      cleanSelectedAvatar();
      selectedProfile = null;
    };
    editorButtons.appendChild(buttonCancel);
    editorDialogForm.appendChild(editorButtons);
    editorDialog.appendChild(editorDialogForm);
    portal.appendChild(editorDialog);

    // ----------------------------------------
    // Delete profile confirmation dialog
    // ----------------------------------------
    const confirmationDialog = document.createElement("dialog");
    confirmationDialog.className = "ProfilePicker-Dialog confirm";
    const confirmationDialogForm = document.createElement("form");
    confirmationDialogForm.method = "dialog";
    confirmationDialogForm.onsubmit = event => {
      sendWithResponse(
        "deleteProfile",
        {
          path: selectedProfile.path,
        },
        () => showProfiles(true),
      );
      confirmationDialog.close();
      selectedProfile = null;
    };
    const confirmationWrapper = document.createElement("div");
    confirmationDialogForm.appendChild(confirmationWrapper);

    // Delete dialog buttons
    const confirmationDialogButtons = document.createElement("div");
    confirmationDialogButtons.className = "ProfilePicker-Buttons";
    const buttonDelete = document.createElement("input");
    buttonDelete.type = "submit";
    buttonDelete.value = buttonDeleteProfileText;
    confirmationDialogButtons.appendChild(buttonDelete);
    const buttonCancelDelete = document.createElement("input");
    buttonCancelDelete.type = "button";
    buttonCancelDelete.value = buttonCancelText;
    buttonCancelDelete.onclick = event => {
      confirmationDialog.close();
      selectedProfile = null;
    };
    confirmationDialogButtons.appendChild(buttonCancelDelete);
    confirmationDialogForm.appendChild(confirmationDialogButtons);
    confirmationDialog.appendChild(confirmationDialogForm);
    portal.appendChild(confirmationDialog);
  });
}

document.addEventListener("DOMContentLoaded", () => {
  showProfiles();
  // Handle window close button
  const closeButton = document.getElementById("window-close-btn");
  if (closeButton) {
    closeButton.addEventListener("click", () => {
      sendWithResponse("closeProfilePicker", {}, () => {});
    });
  }
});
