/* eslint-disable mozilla/no-arbitrary-setTimeout */
"use strict";
const kIteratorTimeout = Services.prefs.getIntPref("findbar.iteratorTimeout");
const kPrefHighlightAll = "findbar.highlightAll";
const kPrefModalHighlight = "findbar.modalHighlight";
add_setup(async function() {
  await SpecialPowers.pushPrefEnv({
    set: [
      [kPrefHighlightAll, true],
      [kPrefModalHighlight, true],
    ],
  });
});
// Test the results of modal highlighting, which is on by default.
add_task(async function testModalResults() {
  let tests = new Map([
    [
      "Roland",
      {
        rectCount: 2,
        insertCalls: [2, 4],
        removeCalls: [0, 1],
        animationCalls: [1, 2],
      },
    ],
    [
      "their law might propagate their kind",
      {
        rectCount: 2,
        insertCalls: [5, 6],
        removeCalls: [4, 5],
        // eslint-disable-next-line object-shorthand
        extraTest: function(maskNode, outlineNode, rects) {
          Assert.equal(
            outlineNode.getElementsByTagName("div").length,
            2,
            "There should be multiple rects drawn"
          );
        },
      },
    ],
    [
      "ro",
      {
        rectCount: 41,
        insertCalls: [1, 4],
        removeCalls: [0, 2],
      },
    ],
    [
      "new",
      {
        rectCount: 2,
        insertCalls: [1, 4],
        removeCalls: [0, 2],
      },
    ],
    [
      "o",
      {
        rectCount: 492,
        insertCalls: [1, 4],
        removeCalls: [0, 2],
      },
    ],
  ]);
  let url = kFixtureBaseURL + "file_FinderSample.html";
  await BrowserTestUtils.withNewTab(url, async function(browser) {
    let findbar = await gBrowser.getFindBar();
    for (let [word, expectedResult] of tests) {
      await promiseOpenFindbar(findbar);
      Assert.ok(!findbar.hidden, "Findbar should be open now.");
      let timeout = kIteratorTimeout;
      if (word.length == 1) {
        timeout *= 4;
      } else if (word.length == 2) {
        timeout *= 2;
      }
      await new Promise(resolve => setTimeout(resolve, timeout));
      let promise = promiseTestHighlighterOutput(
        browser,
        word,
        expectedResult,
        expectedResult.extraTest
      );
      await promiseEnterStringIntoFindField(findbar, word);
      await promise;
      findbar.close(true);
    }
  });
});
// Test if runtime switching of highlight modes between modal and non-modal works
// as expected.
add_task(async function testModalSwitching() {
  let url = kFixtureBaseURL + "file_FinderSample.html";
  await BrowserTestUtils.withNewTab(url, async function(browser) {
    let findbar = await gBrowser.getFindBar();
    await promiseOpenFindbar(findbar);
    Assert.ok(!findbar.hidden, "Findbar should be open now.");
    let word = "Roland";
    let expectedResult = {
      rectCount: 2,
      insertCalls: [2, 4],
      removeCalls: [0, 1],
    };
    let promise = promiseTestHighlighterOutput(browser, word, expectedResult);
    await promiseEnterStringIntoFindField(findbar, word);
    await promise;
    await SpecialPowers.pushPrefEnv({ set: [[kPrefModalHighlight, false]] });
    expectedResult = {
      rectCount: 0,
      insertCalls: [0, 0],
      removeCalls: [0, 0],
    };
    promise = promiseTestHighlighterOutput(browser, word, expectedResult);
    findbar.clear();
    await promiseEnterStringIntoFindField(findbar, word);
    await promise;
    findbar.close(true);
  });
  await SpecialPowers.pushPrefEnv({ set: [[kPrefModalHighlight, true]] });
});
// Test if highlighting a dark page is detected properly.
add_task(async function testDarkPageDetection() {
  let url = kFixtureBaseURL + "file_FinderSample.html";
  await BrowserTestUtils.withNewTab(url, async function(browser) {
    let findbar = await gBrowser.getFindBar();
    await promiseOpenFindbar(findbar);
    let word = "Roland";
    let expectedResult = {
      rectCount: 2,
      insertCalls: [1, 3],
      removeCalls: [0, 1],
    };
    let promise = promiseTestHighlighterOutput(
      browser,
      word,
      expectedResult,
      function(node) {
        Assert.ok(
          node.style.background.startsWith("rgba(0, 0, 0"),
          "White HTML page should have a black background color set for the mask"
        );
      }
    );
    await promiseEnterStringIntoFindField(findbar, word);
    await promise;
    findbar.close(true);
  });
  await BrowserTestUtils.withNewTab(url, async function(browser) {
    let findbar = await gBrowser.getFindBar();
    await promiseOpenFindbar(findbar);
    let word = "Roland";
    let expectedResult = {
      rectCount: 2,
      insertCalls: [2, 4],
      removeCalls: [0, 1],
    };
    await SpecialPowers.spawn(browser, [], async function() {
      let dwu = content.windowUtils;
      let uri =
        "data:text/css;charset=utf-8," +
        encodeURIComponent(`
        body {
          background: maroon radial-gradient(circle, #a01010 0%, #800000 80%) center center / cover no-repeat;
          color: white;
        }`);
      try {
        dwu.loadSheetUsingURIString(uri, dwu.USER_SHEET);
      } catch (e) {}
    });
    let promise = promiseTestHighlighterOutput(
      browser,
      word,
      expectedResult,
      node => {
        Assert.ok(
          node.style.background.startsWith("rgba(255, 255, 255"),
          "Dark HTML page should have a white background color set for the mask"
        );
      }
    );
    await promiseEnterStringIntoFindField(findbar, word);
    await promise;
    findbar.close(true);
  });
});
add_task(async function testHighlightAllToggle() {
  let url = kFixtureBaseURL + "file_FinderSample.html";
  await BrowserTestUtils.withNewTab(url, async function(browser) {
    let findbar = await gBrowser.getFindBar();
    await promiseOpenFindbar(findbar);
    let word = "Roland";
    let expectedResult = {
      rectCount: 2,
      insertCalls: [2, 4],
      removeCalls: [0, 1],
    };
    let promise = promiseTestHighlighterOutput(browser, word, expectedResult);
    await promiseEnterStringIntoFindField(findbar, word);
    await promise;
    // We now know we have multiple rectangles highlighted, so it's a good time
    // to flip the pref.
    expectedResult = {
      rectCount: 0,
      insertCalls: [0, 1],
      removeCalls: [1, 2],
    };
    promise = promiseTestHighlighterOutput(browser, word, expectedResult);
    await SpecialPowers.pushPrefEnv({ set: [[kPrefHighlightAll, false]] });
    await promise;
    // For posterity, let's switch back.
    expectedResult = {
      rectCount: 2,
      insertCalls: [1, 3],
      removeCalls: [0, 1],
    };
    promise = promiseTestHighlighterOutput(browser, word, expectedResult);
    await SpecialPowers.pushPrefEnv({ set: [[kPrefHighlightAll, true]] });
    await promise;
  });
});
add_task(async function testXMLDocument() {
  let url =
    "data:text/xml;charset=utf-8," +
    encodeURIComponent(`