/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/**
 * Tests message moves with filter and quarantine enabled per bug 582918.
 * It then tests that subsequent moves of the filtered messages work.
 *
 * adapted from test_copyThenMoveManual.js
 */

var { MailServices } = ChromeUtils.importESModule(
  "resource:///modules/MailServices.sys.mjs"
);
const { PromiseTestUtils } = ChromeUtils.importESModule(
  "resource://testing-common/mailnews/PromiseTestUtils.sys.mjs"
);

/* import-globals-from ../../../test/resources/POP3pump.js */
load("../../../resources/POP3pump.js");

var gFiles = ["../../../data/bugmail1", "../../../data/bugmail10"];

var gMoveFolder, gMoveFolder2;
var gFilter; // the test filter
var gFilterList;
add_task(async function createFilters() {
  gFilterList = gPOP3Pump.fakeServer.getFilterList(null);
  gFilter = gFilterList.createFilter("MoveAll");
  const searchTerm = gFilter.createTerm();
  searchTerm.matchAll = true;
  gFilter.appendTerm(searchTerm);
  const moveAction = gFilter.createAction();
  moveAction.type = Ci.nsMsgFilterAction.MoveToFolder;
  moveAction.targetFolderUri = gMoveFolder.URI;
  gFilter.appendAction(moveAction);
  gFilter.enabled = true;
  gFilter.filterType = Ci.nsMsgFilterType.InboxRule;
  gFilterList.insertFilterAt(0, gFilter);
});

// just get a message into the local folder
add_task(async function getLocalMessages1() {
  gPOP3Pump.files = gFiles;
  const promise1 = PromiseTestUtils.promiseFolderNotification(
    gMoveFolder,
    "msgsClassified"
  );
  const promise2 = gPOP3Pump.run();
  await Promise.all([promise1, promise2]);
});

add_task(async function verifyFolders1() {
  Assert.equal(folderCount(gMoveFolder), 2);
  // the local inbox folder should now be empty, since the second
  // operation was a move
  Assert.equal(folderCount(localAccountUtils.inboxFolder), 0);

  const msgs = [...gMoveFolder.msgDatabase.enumerateMessages()];
  const firstMsgHdr = msgs[0];
  const secondMsgHdr = msgs[1];
  // Check that the messages have content
  let messageContent = await getContentFromMessage(firstMsgHdr);
  Assert.ok(messageContent.includes("Some User <bugmail@example.org> changed"));
  messageContent = await getContentFromMessage(secondMsgHdr);
  Assert.ok(
    messageContent.includes(
      "https://bugzilla.mozilla.org/show_bug.cgi?id=436880"
    )
  );
});

add_task(async function copyMovedMessages() {
  const msgs = [...gMoveFolder.msgDatabase.enumerateMessages()];
  const firstMsgHdr = msgs[0];
  const secondMsgHdr = msgs[1];
  const promiseCopyListener = new PromiseTestUtils.PromiseCopyListener();
  const promiseMoveMsg = PromiseTestUtils.promiseFolderNotification(
    gMoveFolder2,
    "msgsMoveCopyCompleted"
  );
  MailServices.copy.copyMessages(
    gMoveFolder,
    [firstMsgHdr, secondMsgHdr],
    gMoveFolder2,
    false,
    promiseCopyListener,
    null,
    false
  );
  await Promise.all([promiseCopyListener.promise, promiseMoveMsg]);
});

add_task(async function verifyFolders2() {
  Assert.equal(folderCount(gMoveFolder2), 2);

  const msgs = [...gMoveFolder2.msgDatabase.enumerateMessages()];
  const firstMsgHdr = msgs[0];
  const secondMsgHdr = msgs[1];
  // Check that the messages have content
  let messageContent = await getContentFromMessage(firstMsgHdr);
  Assert.ok(messageContent.includes("Some User <bugmail@example.org> changed"));
  messageContent = await getContentFromMessage(secondMsgHdr);
  Assert.ok(
    messageContent.includes(
      "https://bugzilla.mozilla.org/show_bug.cgi?id=436880"
    )
  );
});

function folderCount(folder) {
  return [...folder.msgDatabase.enumerateMessages()].length;
}

add_setup(async function () {
  // quarantine messages
  Services.prefs.setBoolPref("mailnews.downloadToTempFile", true);
  if (!localAccountUtils.inboxFolder) {
    localAccountUtils.loadLocalMailAccount();
  }

  gMoveFolder = localAccountUtils.rootFolder.createLocalSubfolder("MoveFolder");
  gMoveFolder2 =
    localAccountUtils.rootFolder.createLocalSubfolder("MoveFolder2");
  registerCleanupFunction(() => {
    gPOP3Pump = null;
  });
});

/**
 * Get the full message content.
 *
 * @param {nsIMsgDBHdr} aMsgHdr - nsIMsgDBHdr object whose text body will be read.
 * @returns {Promise<string>} full message contents.
 */
function getContentFromMessage(aMsgHdr) {
  const msgFolder = aMsgHdr.folder;
  const msgUri = msgFolder.getUriForMsg(aMsgHdr);

  return new Promise((resolve, reject) => {
    const streamListener = {
      QueryInterface: ChromeUtils.generateQI(["nsIStreamListener"]),
      sis: Cc["@mozilla.org/scriptableinputstream;1"].createInstance(
        Ci.nsIScriptableInputStream
      ),
      content: "",
      onDataAvailable(request, inputStream, offset, count) {
        this.sis.init(inputStream);
        this.content += this.sis.read(count);
      },
      onStartRequest() {},
      onStopRequest(request, statusCode) {
        this.sis.close();
        if (Components.isSuccessCode(statusCode)) {
          resolve(this.content);
        } else {
          reject(new Error(statusCode));
        }
      },
    };
    MailServices.messageServiceFromURI(msgUri).streamMessage(
      msgUri,
      streamListener,
      null,
      null,
      false,
      "",
      false
    );
  });
}
