ChromeUtils.import("resource://gre/modules/FileUtils.jsm");
ChromeUtils.import("resource://gre/modules/DownloadLastDir.jsm");

/**
 * Tests how the browser remembers the last download folder
 * from download to download, with a particular emphasis
 * on how it behaves when private browsing windows open.
 */
add_task(async function test_downloads_last_dir_toggle() {
  let tmpDir = FileUtils.getDir("TmpD", [], true);
  let dir1 = newDirectory();

  registerCleanupFunction(function() {
    Services.prefs.clearUserPref("browser.download.lastDir");
    dir1.remove(true);
  });

  let win = await BrowserTestUtils.openNewBrowserWindow();
  let gDownloadLastDir = new DownloadLastDir(win);
  is(typeof gDownloadLastDir, "object",
     "gDownloadLastDir should be a valid object");
  is(gDownloadLastDir.file, null,
     "gDownloadLastDir.file should be null to start with");

  gDownloadLastDir.file = tmpDir;
  is(gDownloadLastDir.file.path, tmpDir.path,
     "LastDir should point to the temporary directory");
  isnot(gDownloadLastDir.file, tmpDir,
        "gDownloadLastDir.file should not be pointing to the tmpDir");

  gDownloadLastDir.file = 1; // not an nsIFile
  is(gDownloadLastDir.file, null, "gDownloadLastDir.file should be null");

  gDownloadLastDir.file = tmpDir;
  clearHistory();
  is(gDownloadLastDir.file, null, "gDownloadLastDir.file should be null");

  gDownloadLastDir.file = tmpDir;
  await BrowserTestUtils.closeWindow(win);

  info("Opening the first private window");
  await testHelper({ private: true, expectedDir: tmpDir });
  info("Opening a non-private window");
  await testHelper({ private: false, expectedDir: tmpDir });
  info("Opening a private window and setting download directory");
  await testHelper({ private: true, setDir: dir1, expectedDir: dir1 });
  info("Opening a non-private window and checking download directory");
  await testHelper({ private: false, expectedDir: tmpDir });
  info("Opening private window and clearing history");
  await testHelper({ private: true, clearHistory: true, expectedDir: null });
  info("Opening a non-private window and checking download directory");
  await testHelper({ private: true, expectedDir: null });
});

/**
 * Opens a new window and performs some test actions on it based
 * on the options object that have been passed in.
 *
 * @param options (Object)
 *        An object with the following properties:
 *
 *        clearHistory (bool, optional):
 *          Whether or not to simulate clearing session history.
 *          Defaults to false.
 *
 *        setDir (nsIFile, optional):
 *          An nsIFile for setting the last download directory.
 *          If not set, the load download directory is not changed.
 *
 *        expectedDir (nsIFile, expectedDir):
 *          An nsIFile for what we expect the last download directory
 *          should be. The nsIFile is not compared directly - only
 *          paths are compared. If expectedDir is not set, then the
 *          last download directory is expected to be null.
 *
 * @returns Promise
 */
async function testHelper(options) {
  let win = await BrowserTestUtils.openNewBrowserWindow(options);
  let gDownloadLastDir = new DownloadLastDir(win);

  if (options.clearHistory) {
    clearHistory();
  }

  if (options.setDir) {
    gDownloadLastDir.file = options.setDir;
  }

  let expectedDir = options.expectedDir;

  if (expectedDir) {
    is(gDownloadLastDir.file.path, expectedDir.path,
       "gDownloadLastDir should point to the expected last directory");
    isnot(gDownloadLastDir.file, expectedDir,
          "gDownloadLastDir.file should not be pointing to the last directory");
  } else {
    is(gDownloadLastDir.file, null, "gDownloadLastDir should be null");
  }

  gDownloadLastDir.cleanupPrivateFile();
  await BrowserTestUtils.closeWindow(win);
}
