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

EXPECTED_BREACH = {
  AddedDate: "2018-12-20T23:56:26Z",
  BreachDate: "2018-12-16",
  Domain: "breached.example.com",
  Name: "Breached",
  PwnCount: 1643100,
  DataClasses: ["Email addresses", "Usernames", "Passwords", "IP addresses"],
  _status: "synced",
  id: "047940fe-d2fd-4314-b636-b4a952ee0043",
  last_modified: "1541615610052",
  schema: "1541615609018",
};

const SORT_PREF_NAME = "signon.management.page.sort";

add_setup(async function () {
  TEST_LOGIN3.QueryInterface(Ci.nsILoginMetaInfo).timePasswordChanged = 1;
  TEST_LOGIN1 = await addLogin(TEST_LOGIN1);
  info(`TEST_LOGIN1 added with guid=${TEST_LOGIN1.guid}`);
  TEST_LOGIN3 = await addLogin(TEST_LOGIN3);
  info(`TEST_LOGIN3 added with guid=${TEST_LOGIN3.guid}`);
  registerCleanupFunction(() => {
    Services.logins.removeAllUserFacingLogins();
    Services.prefs.clearUserPref(SORT_PREF_NAME);
  });
});

add_task(async function test_sort_order_persisted() {
  await BrowserTestUtils.withNewTab(
    {
      gBrowser,
      url: "about:logins",
    },
    async function (browser) {
      await ContentTask.spawn(
        browser,
        [TEST_LOGIN1.guid, TEST_LOGIN3.guid],
        async function ([testLogin1Guid, testLogin3Guid]) {
          let loginList = Cu.waiveXrays(
            content.document.querySelector("login-list")
          );
          await ContentTaskUtils.waitForCondition(
            () => loginList._sortSelect.value == "alerts",
            "Waiting for login-list sort to get changed to 'alerts'. Current value is: " +
              loginList._sortSelect.value
          );
          Assert.equal(
            loginList._sortSelect.value,
            "alerts",
            "selected sort should be 'alerts' since there is a breached login"
          );
          Assert.equal(
            loginList._list.querySelector(
              ".login-list-item[data-guid]:not([hidden])"
            ).dataset.guid,
            testLogin3Guid,
            "the first login should be TEST_LOGIN3 since they are sorted by alerts"
          );

          loginList._sortSelect.value = "last-changed";
          loginList._sortSelect.dispatchEvent(
            new content.Event("change", { bubbles: true })
          );
          Assert.equal(
            loginList._list.querySelector(
              ".login-list-item[data-guid]:not([hidden])"
            ).dataset.guid,
            testLogin1Guid,
            "the first login should be TEST_LOGIN1 since it has the most recent timePasswordChanged value"
          );
        }
      );
    }
  );

  Assert.equal(
    Services.prefs.getCharPref(SORT_PREF_NAME),
    "last-changed",
    "'last-changed' should be stored in the pref"
  );

  // Set the pref to the value used in Fx70-76 to confirm our
  // backwards-compat support that "breached" is changed to "alerts"
  Services.prefs.setCharPref(SORT_PREF_NAME, "breached");
  await BrowserTestUtils.withNewTab(
    {
      gBrowser,
      url: "about:logins",
    },
    async function (browser) {
      await ContentTask.spawn(
        browser,
        TEST_LOGIN3.guid,
        async function (testLogin3Guid) {
          let loginList = Cu.waiveXrays(
            content.document.querySelector("login-list")
          );
          await ContentTaskUtils.waitForCondition(
            () => loginList._sortSelect.value == "alerts",
            "Waiting for login-list sort to get changed to 'alerts'. Current value is: " +
              loginList._sortSelect.value
          );
          Assert.equal(
            loginList._sortSelect.value,
            "alerts",
            "selected sort should be restored to 'alerts' since 'breached' was in prefs"
          );
          Assert.equal(
            loginList._list.querySelector(
              ".login-list-item[data-guid]:not([hidden])"
            ).dataset.guid,
            testLogin3Guid,
            "the first login should be TEST_LOGIN3 since they are sorted by alerts"
          );
        }
      );
    }
  );

  let storageChangedPromised = TestUtils.topicObserved(
    "passwordmgr-storage-changed",
    (_, data) => data == "removeLogin"
  );
  Services.logins.removeLogin(TEST_LOGIN3);
  await storageChangedPromised;
  TEST_LOGIN2 = await addLogin(TEST_LOGIN2);

  Assert.equal(
    Services.prefs.getCharPref(SORT_PREF_NAME),
    "breached",
    "confirm that the stored sort is still 'breached' and as such shouldn't apply when the page loads"
  );
  await BrowserTestUtils.withNewTab(
    {
      gBrowser,
      url: "about:logins",
    },
    async function (browser) {
      await ContentTask.spawn(
        browser,
        TEST_LOGIN2.guid,
        async function (testLogin2Guid) {
          let loginList = Cu.waiveXrays(
            content.document.querySelector("login-list")
          );
          await ContentTaskUtils.waitForCondition(
            () =>
              loginList._list.querySelector(
                ".login-list-item[data-guid]:not([hidden])"
              ),
            "wait for a visible loging to get populated"
          );
          Assert.equal(
            loginList._sortSelect.value,
            "name",
            "selected sort should be name since 'alerts' no longer applies with no breached or vulnerable logins"
          );
          Assert.equal(
            loginList._list.querySelector(
              ".login-list-item[data-guid]:not([hidden])"
            ).dataset.guid,
            testLogin2Guid,
            "the first login should be TEST_LOGIN2 since it is sorted first by 'name'"
          );
        }
      );
    }
  );
});
