/* 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 that you can stream a message without the attachments. Tests the
 * MsgHdrToMimeMessage API that exposes this.
 */
var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
Services.prefs.setIntPref("mail.imap.mime_parts_on_demand_threshold", 1000);

/* import-globals-from ../../../test/resources/logHelper.js */
/* import-globals-from ../../../test/resources/asyncTestUtils.js */
/* import-globals-from ../../../test/resources/messageGenerator.js */
load("../../../resources/logHelper.js");
load("../../../resources/asyncTestUtils.js");
load("../../../resources/messageGenerator.js");

// javascript mime emitter functions
var mimeMsg = {};
ChromeUtils.import("resource:///modules/gloda/mimemsg.js", mimeMsg);

var gSecondMsg;

// IMAP pump

setupIMAPPump();

var tests = [
  setPrefs,
  loadImapMessage,
  startMime,
  testAllInlineMessage,
  updateCounts,
  testNotRead,
  endTest,
];

// make sure we are in the optimal conditions!
function* setPrefs() {
  Services.prefs.setIntPref("mail.imap.mime_parts_on_demand_threshold", 20);
  Services.prefs.setBoolPref("mail.imap.mime_parts_on_demand", true);
  Services.prefs.setBoolPref("mail.server.server1.autosync_offline_stores", false);
  Services.prefs.setBoolPref("mail.server.server1.offline_download", false);
  Services.prefs.setBoolPref("mail.server.server1.download_on_biff", false);
  Services.prefs.setIntPref("browser.cache.disk.capacity", 0);

  yield true;
}

// load and update a message in the imap fake server
function* loadImapMessage() {
  let file = do_get_file("../../../data/bodystructuretest1");
  let msgURI = Services.io.newFileURI(file).QueryInterface(Ci.nsIFileURL);

  let imapInbox = IMAPPump.daemon.getMailbox("INBOX");
  let message = new imapMessage(msgURI.spec, imapInbox.uidnext++, []);
  IMAPPump.mailbox.addMessage(message);
  // add a second message with no external parts. We want to make
  // sure that streaming this message doesn't mark it read, even
  // though we will fallback to fetching the whole message.
  file = do_get_file("../../../data/bodystructuretest3");
  msgURI = Services.io.newFileURI(file).QueryInterface(Ci.nsIFileURL);
  message = new imapMessage(msgURI.spec, imapInbox.uidnext++, []);
  IMAPPump.mailbox.addMessage(message);
  IMAPPump.inbox.updateFolderWithListener(null, asyncUrlListener);
  yield false;

  Assert.equal(2, IMAPPump.inbox.getTotalMessages(false));
  let msgHdr = mailTestUtils.firstMsgHdr(IMAPPump.inbox);
  Assert.ok(msgHdr instanceof Ci.nsIMsgDBHdr);
  yield true;
}

// process the message through mime
function* startMime() {
  let msgHdr = mailTestUtils.firstMsgHdr(IMAPPump.inbox);

  mimeMsg.MsgHdrToMimeMessage(msgHdr, this, function(aMsgHdr, aMimeMessage) {
    let url = aMimeMessage.allUserAttachments[0].url;
    // A URL containing this string indicates that the attachment will be
    // downloaded on demand.
    Assert.ok(url.includes("/;section="));
    async_driver();
  }, true /* allowDownload */, { partsOnDemand: true, examineEncryptedParts: true });
  yield false;
}

// test that we don't mark all inline messages as read.
function* testAllInlineMessage() {
  let enumerator = IMAPPump.inbox.msgDatabase.EnumerateMessages();

  if (enumerator.hasMoreElements()) {
    gSecondMsg = enumerator.getNext().QueryInterface(Ci.nsIMsgDBHdr);
    mimeMsg.MsgHdrToMimeMessage(gSecondMsg, this, function(aMsgHdr, aMimeMessage) {
      async_driver();
    }, true /* allowDownload */, { partsOnDemand: true });
    yield false;
  }
}

function* updateCounts() {
  // select the trash, then the inbox again, to force an update of the
  // read state of messages.
  let trash = IMAPPump.incomingServer.rootFolder.getChildNamed("Trash");
  Assert.ok(trash instanceof Ci.nsIMsgImapMailFolder);
  trash.updateFolderWithListener(null, asyncUrlListener);
  yield false;
  IMAPPump.inbox.updateFolderWithListener(null, asyncUrlListener);
  yield false;
}

function* testNotRead() {
  Assert.equal(2, IMAPPump.inbox.getNumUnread(false));
  yield true;
}

// Cleanup
function endTest() {
  teardownIMAPPump();
}

function run_test() {
  async_run_tests(tests);
}
