text: // Generated by CoffeeScript 1.10.0
  var Account, AccountConfigError, BadRequest, MSGBYPAGE, Mailbox, Message, MessageMove, NotFound, SaveOrSendMessage, _, async, crlf, log, minifierOpts, minify, multiparty, normalizeMessageID, querystring, ramStore, ref, stream_to_buffer, uuid;
  
  Message = require('../models/message');
  
  Account = require('../models/account');
  
  Mailbox = require('../models/mailbox');
  
  ref = require('../utils/errors'), NotFound = ref.NotFound, BadRequest = ref.BadRequest, AccountConfigError = ref.AccountConfigError;
  
  MSGBYPAGE = require('../utils/constants').MSGBYPAGE;
  
  _ = require('lodash');
  
  async = require('async');
  
  querystring = require('querystring');
  
  multiparty = require('multiparty');
  
  crlf = require('crlf-helper');
  
  minify = require('html-minifier').minify;
  
  stream_to_buffer = require('../utils/stream_to_array');
  
  log = require('../utils/logging')({
    prefix: 'controllers:mesage'
  });
  
  normalizeMessageID = require('../utils/jwz_tools').normalizeMessageID;
  
  uuid = require('uuid');
  
  ramStore = require('../models/store_account_and_boxes');
  
  SaveOrSendMessage = require('../processes/message_save_or_send');
  
  MessageMove = require('../processes/message_move');
  
  minifierOpts = {
    removeComments: true,
    removeCommentsFromCDATA: true,
    collapseWhitespace: true,
    collapseBooleanAttributes: true,
    removeRedundantAttributes: true,
    removeEmptyAttributes: true,
    removeScriptTypeAttributes: true,
    removeStyleLinkTypeAttributes: true,
    removeOptionalTags: true,
    removeEmptyElements: true,
    keepClosingSlash: true,
    minifyJS: true,
    minifyCSS: true
  };
  
  module.exports.fetch = function(req, res, next) {
    var id;
    id = req.params.messageID || req.body.id;
    return Message.find(id, function(err, found) {
      if (err) {
        return next(err);
      }
      if (!found) {
        return next(new NotFound("Message " + id));
      }
      req.message = found;
      return next();
    });
  };
  
  module.exports.fetchMaybe = function(req, res, next) {
    var id;
    id = req.body.id;
    if (id) {
      return module.exports.fetch(req, res, next);
    } else {
      return next();
    }
  };
  
  module.exports.details = function(req, res, next) {
    return res.send(req.message.toClientObject());
  };
  
  module.exports.attachment = function(req, res, next) {
    var encodedFileName, ref1, stream;
    stream = req.message.getBinary(req.params.attachment, function(err) {
      if (err) {
        return next(err);
      }
    });
    if ((ref1 = req.query) != null ? ref1.download : void 0) {
      encodedFileName = encodeURIComponent(req.params.attachment);
      res.setHeader('Content-disposition', "attachment; filename*=UTF8''" + encodedFileName);
    }
    return stream.pipe(res);
  };
  
  module.exports.listByMailboxOptions = function(req, res, next) {
    var FLAGS_CONVERT, after, before, descending, flag, flagcode, pageAfter, sort, sortField;
    sort = req.query.sort ? req.query.sort : '-date';
    descending = sort.substring(0, 1);
    if (descending === '+') {
      descending = false;
    } else if (descending === '-') {
      descending = true;
    } else {
      return next(new BadRequest("Unsuported sort order " + descending));
    }
    pageAfter = req.query.pageAfter;
    sortField = sort.substring(1);
    before = req.query.before;
    after = req.query.after;
    if (sortField === 'date') {
      if (before == null) {
        before = new Date(0).toISOString();
      }
      if (after == null) {
        after = new Date().toISOString();
      }
      if (new Date(before).toISOString() !== before || new Date(after).toISOString() !== after) {
        return next(new BadRequest("before & after should be a valid JS " + "date.toISOString()"));
      }
    } else if (sortField === 'from' || sortField === 'dest') {
      before = before ? decodeURIComponent(before) : '';
      after = after ? decodeURIComponent(after) : {};
      pageAfter = pageAfter ? decodeURIComponent(pageAfter) : void 0;
    } else {
      return next(new BadRequest("Unsuported sort field " + sortField));
    }
    FLAGS_CONVERT = {
      'seen': '\\Seen',
      'unseen': '!\\Seen',
      'flagged': '\\Flagged',
      'unflagged': '!\\Flagged',
      'answered': '\\Answered',
      'unanswered': '!\\Answered',
      'attach': '\\Attachments'
    };
    flagcode = req.query.flag;
    if (flagcode) {
      if (!(flag = FLAGS_CONVERT[flagcode])) {
        return next(new BadRequest("Unsuported flag filter"));
      }
    } else {
      flag = null;
    }
    req.sortField = sortField;
    req.descending = descending;
    req.before = before;
    req.sort = sort;
    req.after = after;
    req.pageAfter = pageAfter;
    req.flag = flag;
    req.flagcode = flagcode;
    return next();
  };
  
  module.exports.listByMailbox = function(req, res, next) {
    var mailboxID;
    mailboxID = req.params.mailboxID;
    return Message.getResultsAndCount(mailboxID, {
      sortField: req.sortField,
      descending: req.descending,
      before: req.before,
      after: req.after,
      resultsAfter: req.pageAfter,
      flag: req.flag
    }, function(err, result) {
      var last, lastDate, links, messages, pageAfter;
      if (err) {
        return next(err);
      }
      messages = result.messages;
      if (messages.length === MSGBYPAGE) {
        last = messages[messages.length - 1];
        if (req.sortField === 'from' || req.sortField === 'dest') {
          pageAfter = messages.length + (parseInt(req.pageAfter, 10) || 0);
        } else {
          lastDate = last.date || new Date();
          pageAfter = lastDate.toISOString();
        }
        links = {
          next: ("mailbox/" + mailboxID + "/?") + querystring.stringify({
            flag: req.flagcode,
            sort: req.sort,
            before: req.before,
            after: req.after,
            pageAfter: pageAfter
          })
        };
      } else {
        links = {};
      }
      if (result.messages == null) {
        result.messages = [];
      }
      result.mailboxID = mailboxID;
      result.messages = result.messages.map(function(msg) {
        return msg.toClientObject();
      });
      result.links = links;
      return res.send(result);
    });
  };
  
  module.exports.parseSendForm = function(req, res, next) {
    var fields, files, form, nextonce;
    form = new multiparty.Form({
      autoFields: true
    });
    nextonce = _.once(next);
    fields = {};
    files = {};
    form.on('field', function(name, value) {
      return fields[name] = value;
    });
    form.on('part', function(part) {
      stream_to_buffer(part, function(err, bufs) {
        if (err) {
          return nextonce(err);
        }
        return files[part.name] = {
          filename: part.filename,
          headers: part.headers,
          content: Buffer.concat(bufs)
        };
      });
      return part.resume();
    });
    form.on('error', function(err) {
      return nextonce(err);
    });
    form.on('close', function() {
      req.body = JSON.parse(fields.body);
      req.files = files;
      return nextonce();
    });
    return form.parse(req);
  };
  
  module.exports.send = function(req, res, next) {
    var isDraft, message, proc;
    log.debug("send");
    isDraft = req.body.isDraft;
    delete req.body.isDraft;
    message = req.body;
    if (message.html) {
      message.html = minify(message.html, minifierOpts);
    }
    if (message.text) {
      message.text = crlf.setLineEnding(message.text.trim(), 'CRLF');
    }
    proc = new SaveOrSendMessage({
      account: ramStore.getAccount(req.body.accountID),
      previousState: req.message,
      message: message,
      newAttachments: req.files,
      isDraft: isDraft
    });
    return proc.run(function(err) {
      var out;
      if (err) {
        return next(err);
      }
      out = proc.cozyMessage.toClientObject();
      out.isDraft = isDraft;
      return res.send(out);
    });
  };
  
  module.exports.batchFetch = function(req, res, next) {
    var handleMessages;
    if (Object.keys(req.body).length === 0) {
      req.body = req.query;
    }
    handleMessages = function(err, messages) {
      if (err) {
        return next(err);
      }
      req.messages = messages;
      return next();
    };
    if (req.body.messageID) {
      return Message.find(req.body.messageID, function(err, message) {
        return handleMessages(err, [message]);
      });
    } else if (req.body.conversationID) {
      return Message.byConversationID(req.body.conversationID, handleMessages);
    } else if (req.body.messageIDs) {
      return Message.findMultiple(req.body.messageIDs, handleMessages);
    } else if (req.body.conversationIDs) {
      return Message.byConversationIDs(req.body.conversationIDs, handleMessages);
    } else {
      return next(new BadRequest("No conversationIDs, conversationID, or messageIDs in body."));
    }
  };
  
  module.exports.batchSend = function(req, res, next) {
    var messages;
    messages = req.messages.filter(function(msg) {
      return msg != null;
    }).map(function(msg) {
      return msg != null ? msg.toClientObject() : void 0;
    });
    if (messages.length === 0) {
      return next(new NotFound("No message found"));
    }
    return res.send(messages);
  };
  
  module.exports.batchTrash = function(req, res, next) {
    var accountInstance, process, trashBoxId;
    accountInstance = ramStore.getAccount(req.body.accountID);
    if (!accountInstance) {
      return next(new BadRequest('accountInstance'));
    }
    trashBoxId = accountInstance.trashMailbox;
    if (!trashBoxId) {
      return next(new AccountConfigError('trashMailbox'));
    }
    process = new MessageMove({
      messages: req.messages,
      to: trashBoxId
    });
    return process.run(function(err) {
      return res.send(process.updatedMessages);
    });
  };
  
  module.exports.batchAddFlag = function(req, res, next) {
    return Message.batchAddFlag(req.messages, req.body.flag, function(err, updated) {
      if (err) {
        return next(err);
      }
      return res.send(updated);
    });
  };
  
  module.exports.batchRemoveFlag = function(req, res, next) {
    return Message.batchRemoveFlag(req.messages, req.body.flag, function(err, updated) {
      if (err) {
        return next(err);
      }
      return res.send(updated);
    });
  };
  
  module.exports.batchMove = function(req, res, next) {
    var process;
    process = new MessageMove({
      messages: req.messages,
      to: req.body.to,
      from: req.body.from
    });
    return process.run(function(err) {
      return res.send(process.updatedMessages);
    });
  };
  
  module.exports.search = function(req, res, next) {
    var params;
    return next(new Error('search is disabled'));
    params = {
      query: req.query.search,
      facets: {
        accountID: {}
      }
    };
    if (req.query.accountID) {
      params.filter = {
        accountID: [[req.query.accountID, req.query.accountID]]
      };
    }
    params.numByPage = req.query.pageSize || 10;
    params.numPage = req.query.page || 0;
    return Message.search(params, function(err, results) {
      var account, accounts, facet, i, j, len, len1, ref1, ref2;
      if (err) {
        return next(err);
      }
      accounts = {};
      ref1 = results.facets;
      for (i = 0, len = ref1.length; i < len; i++) {
        facet = ref1[i];
        if (facet.key === 'accountID') {
          ref2 = facet.value;
          for (j = 0, len1 = ref2.length; j < len1; j++) {
            account = ref2[j];
            accounts[account.key] = account.value;
          }
        }
      }
      return res.send({
        accounts: accounts,
        rows: results.map(function(msg) {
          return msg.toClientObject();
        })
      });
    });
  };
  
  module.exports.raw = function(req, res, next) {
    var boxID, uid;
    boxID = Object.keys(req.message.mailboxIDs)[0];
    uid = req.message.mailboxIDs[boxID];
    return Mailbox.find(boxID, function(err, mailbox) {
      if (err) {
        return next(err);
      }
      return mailbox.doASAPWithBox(function(imap, imapbox, cbRelease) {
        var error;
        try {
          return imap.fetchOneMailRaw(uid, cbRelease);
        } catch (error) {
          err = error;
          return cbRelease(err);
        }
      }, function(err, message) {
        if (err) {
          return next(err);
        }
        res.type('text/plain');
        return res.send(message);
      });
    });
  };
  