/* Any copyright is dedicated to the Public Domain.
 * http://creativecommons.org/publicdomain/zero/1.0/ */

"use strict";

/**
 * Test window type detection and menu item visibility based on aiwindow pref and window type.
 */
add_task(async function test_window_type_and_menu_visibility() {
  // AI Window disabled
  await SpecialPowers.pushPrefEnv({
    set: [["browser.aiwindow.enabled", false]],
  });

  await openHamburgerMenu();
  checkMenuItemVisibility(
    false,
    document.getElementById("appMenu-new-ai-window-button"),
    document.getElementById("appMenu-new-classic-window-button")
  );
  await closeHamburgerMenu();

  let fileMenuPopup = document.getElementById("menu_FilePopup");
  if (fileMenuPopup) {
    await openFileMenu(fileMenuPopup);
    checkMenuItemVisibility(
      false,
      document.getElementById("menu_newAIWindow"),
      document.getElementById("menu_newClassicWindow")
    );
    await closeFileMenu(fileMenuPopup);
  }

  await SpecialPowers.popPrefEnv();

  // AI Window enabled
  await SpecialPowers.pushPrefEnv({
    set: [["browser.aiwindow.enabled", true]],
  });

  await openHamburgerMenu();
  checkMenuItemVisibility(
    true,
    document.getElementById("appMenu-new-ai-window-button"),
    document.getElementById("appMenu-new-classic-window-button")
  );
  await closeHamburgerMenu();

  if (fileMenuPopup) {
    await openFileMenu(fileMenuPopup);
    checkMenuItemVisibility(
      true,
      document.getElementById("menu_newAIWindow"),
      document.getElementById("menu_newClassicWindow")
    );
    await closeFileMenu(fileMenuPopup);
  }

  await SpecialPowers.popPrefEnv();
});

/**
 * Test that clicking AI window and classic window buttons opens the correct window type.
 */
add_task(async function test_button_actions() {
  await SpecialPowers.pushPrefEnv({
    set: [["browser.aiwindow.enabled", true]],
  });

  const currentWindowIsAIWindow = isAIWindow();

  await openHamburgerMenu();

  const buttonId = currentWindowIsAIWindow
    ? "appMenu-new-classic-window-button"
    : "appMenu-new-ai-window-button";
  const button = document.getElementById(buttonId);

  if (button && !button.hidden) {
    let delayedStartupPromise = BrowserTestUtils.waitForNewWindow();
    button.click();

    const newWin = await delayedStartupPromise;
    const newWinIsAI =
      newWin.document.documentElement.hasAttribute("ai-window");

    Assert.equal(
      newWinIsAI,
      !currentWindowIsAIWindow,
      `Clicking ${currentWindowIsAIWindow ? "classic" : "AI"} window button should open a ${currentWindowIsAIWindow ? "classic" : "AI"} window`
    );

    if (newWinIsAI) {
      let fileMenuPopup = newWin.document.getElementById("menu_FilePopup");

      await openHamburgerMenu(newWin);
      checkMenuItemVisibility(
        true,
        newWin.document.getElementById("appMenu-new-ai-window-button"),
        newWin.document.getElementById("appMenu-new-classic-window-button")
      );
      await closeHamburgerMenu(newWin);

      if (fileMenuPopup) {
        await openFileMenu(fileMenuPopup);
        checkMenuItemVisibility(
          true,
          newWin.document.getElementById("menu_newAIWindow"),
          newWin.document.getElementById("menu_newClassicWindow")
        );
        await closeFileMenu(fileMenuPopup);
      }
    }

    await BrowserTestUtils.closeWindow(newWin);
  } else {
    await closeHamburgerMenu();
  }

  await openHamburgerMenu();

  const appMenuNewWindow = document.getElementById(
    "appMenu-new-window-button2"
  );
  if (appMenuNewWindow && !appMenuNewWindow.hidden) {
    let delayedStartupPromise = BrowserTestUtils.waitForNewWindow();
    appMenuNewWindow.click();

    const newWin = await delayedStartupPromise;
    const newWinIsAI =
      newWin.document.documentElement.hasAttribute("ai-window");

    Assert.equal(
      newWinIsAI,
      currentWindowIsAIWindow,
      "New window button should open same type as current window"
    );

    await BrowserTestUtils.closeWindow(newWin);
  }

  const appMenuPopup = document.getElementById("appMenu-popup");
  if (appMenuPopup && appMenuPopup.state !== "closed") {
    await closeHamburgerMenu();
  }

  await SpecialPowers.popPrefEnv();
});

function checkMenuItemVisibility(
  aiWindowEnabled,
  aiOpenerButton,
  classicOpenerButton
) {
  const doc =
    aiOpenerButton?.ownerDocument ||
    classicOpenerButton?.ownerDocument ||
    document;
  const currentWindowIsAIWindow = doc.documentElement.hasAttribute("ai-window");

  if (!aiWindowEnabled) {
    Assert.ok(
      !aiOpenerButton || aiOpenerButton.hidden,
      `AI Window button should not be visible when browser.aiwindow.enabled is false`
    );
    Assert.ok(
      !classicOpenerButton || classicOpenerButton.hidden,
      `Classic Window button should not be visible when browser.aiwindow.enabled is false`
    );
  } else if (currentWindowIsAIWindow) {
    Assert.ok(
      !aiOpenerButton || aiOpenerButton.hidden,
      `AI Window button should be hidden in AI Window when browser.aiwindow.enabled is true`
    );
    Assert.ok(
      classicOpenerButton && !classicOpenerButton.hidden,
      `Classic Window button should be visible in AI Window when browser.aiwindow.enabled is true`
    );
  } else {
    Assert.ok(
      aiOpenerButton && !aiOpenerButton.hidden,
      `AI Window button should be visible in Classic Window when browser.aiwindow.enabled is true`
    );
    Assert.ok(
      !classicOpenerButton || classicOpenerButton.hidden,
      `Classic Window button should be hidden in Classic Window when browser.aiwindow.enabled is true`
    );
  }
}

function isAIWindow() {
  return window.document.documentElement.hasAttribute("ai-window");
}

async function openHamburgerMenu(aiWindow = null) {
  let menuButton = aiWindow
    ? aiWindow.document.getElementById("PanelUI-menu-button")
    : document.getElementById("PanelUI-menu-button");
  let mainView = aiWindow
    ? PanelMultiView.getViewNode(aiWindow.document, "appMenu-mainView")
    : PanelMultiView.getViewNode(document, "appMenu-mainView");

  let viewShownPromise = BrowserTestUtils.waitForEvent(mainView, "ViewShown");
  menuButton.click();
  await viewShownPromise;
}

async function closeHamburgerMenu(aiWindow = null) {
  let appMenuPopup = aiWindow
    ? aiWindow.document.getElementById("appMenu-popup")
    : document.getElementById("appMenu-popup");

  let panelHiddenPromise = BrowserTestUtils.waitForEvent(
    appMenuPopup,
    "popuphidden"
  );

  if (aiWindow) {
    aiWindow.PanelUI.hide();
  } else {
    PanelUI.hide();
  }
  await panelHiddenPromise;
}

async function openFileMenu(menu) {
  return new Promise(resolve => {
    menu.addEventListener("popupshown", resolve, { once: true });
    menu.dispatchEvent(new MouseEvent("popupshowing", { bubbles: true }));
    menu.dispatchEvent(new MouseEvent("popupshown", { bubbles: true }));
  });
}

async function closeFileMenu(menu) {
  return new Promise(resolve => {
    menu.addEventListener("popuphidden", resolve, { once: true });
    menu.dispatchEvent(new MouseEvent("popuphiding", { bubbles: true }));
    menu.dispatchEvent(new MouseEvent("popuphidden", { bubbles: true }));
  });
}
