/*
 * Copyright (C) 2008-2009 Marc Blank
 * Licensed to The Android Open Source Project.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.exchange;

import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.TrafficStats;
import android.net.Uri;
import android.os.RemoteException;
import android.text.TextUtils;

import com.android.emailcommon.TrafficFlags;
import com.android.emailcommon.internet.Rfc822Output;
import com.android.emailcommon.mail.MessagingException;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.EmailContent.Body;
import com.android.emailcommon.provider.EmailContent.BodyColumns;
import com.android.emailcommon.provider.EmailContent.MailboxColumns;
import com.android.emailcommon.provider.EmailContent.Message;
import com.android.emailcommon.provider.EmailContent.MessageColumns;
import com.android.emailcommon.provider.EmailContent.SyncColumns;
import com.android.emailcommon.provider.Mailbox;
import com.android.emailcommon.service.EmailServiceStatus;
import com.android.emailcommon.utility.Utility;
import com.android.exchange.CommandStatusException.CommandStatus;
import com.android.exchange.adapter.Parser;
import com.android.exchange.adapter.Parser.EmptyStreamException;
import com.android.exchange.adapter.Serializer;
import com.android.exchange.adapter.Tags;

import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.entity.InputStreamEntity;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class EasOutboxService extends EasSyncService {

    public static final int SEND_FAILED = 1;
    public static final String MAILBOX_KEY_AND_NOT_SEND_FAILED =
        MessageColumns.MAILBOX_KEY + "=? and (" + SyncColumns.SERVER_ID + " is null or " +
        SyncColumns.SERVER_ID + "!=" + SEND_FAILED + ')';
    public static final String[] BODY_SOURCE_PROJECTION =
        new String[] {BodyColumns.SOURCE_MESSAGE_KEY};
    public static final String WHERE_MESSAGE_KEY = Body.MESSAGE_KEY + "=?";

    // This is a normal email (i.e. not one of the other types)
    public static final int MODE_NORMAL = 0;
    // This is a smart reply email
    public static final int MODE_SMART_REPLY = 1;
    // This is a smart forward email
    public static final int MODE_SMART_FORWARD = 2;

    // This needs to be long enough to send the longest reasonable message, without being so long
    // as to effectively "hang" sending of mail.  The standard 30 second timeout isn't long enough
    // for pictures and the like.  For now, we'll use 15 minutes, in the knowledge that any socket
    // failure would probably generate an Exception before timing out anyway
    public static final int SEND_MAIL_TIMEOUT = 15*MINUTES;

    public EasOutboxService(Context _context, Mailbox _mailbox) {
        super(_context, _mailbox);
    }

    /**
     * Our own HttpEntity subclass that is able to insert opaque data (in this case the MIME
     * representation of the message body as stored in a temporary file) into the serializer stream
     */
    private static class SendMailEntity extends InputStreamEntity {
        private final Context mContext;
        private final FileInputStream mFileStream;
        private final long mFileLength;
        private final int mSendTag;
        private final Message mMessage;

        private static final int[] MODE_TAGS =  new int[] {Tags.COMPOSE_SEND_MAIL,
            Tags.COMPOSE_SMART_REPLY, Tags.COMPOSE_SMART_FORWARD};

        public SendMailEntity(Context context, FileInputStream instream, long length, int tag,
                Message message) {
            super(instream, length);
            mContext = context;
            mFileStream = instream;
            mFileLength = length;
            mSendTag = tag;
            mMessage = message;
        }

        /**
         * We always return -1 because we don't know the actual length of the POST data (this
         * causes HttpClient to send the data in "chunked" mode)
         */
        @Override
        public long getContentLength() {
            return -1;
        }

        @Override
        public void writeTo(OutputStream outstream) throws IOException {
            // Not sure if this is possible; the check is taken from the superclass
            if (outstream == null) {
                throw new IllegalArgumentException("Output stream may not be null");
            }

            // We'll serialize directly into the output stream
            Serializer s = new Serializer(outstream);
            // Send the appropriate initial tag
            s.start(mSendTag);
            // The Message-Id for this message (note that we cannot use the messageId stored in
            // the message, as EAS 14 limits the length to 40 chars and we use 70+)
            s.data(Tags.COMPOSE_CLIENT_ID, "SendMail-" + System.nanoTime());
            // We always save sent mail
            s.tag(Tags.COMPOSE_SAVE_IN_SENT_ITEMS);

            // If we're using smart reply/forward, we need info about the original message
            if (mSendTag != Tags.COMPOSE_SEND_MAIL) {
                OriginalMessageInfo info = getOriginalMessageInfo(mContext, mMessage.mId);
                if (info != null) {
                    s.start(Tags.COMPOSE_SOURCE);
                    // For search results, use the long id (stored in mProtocolSearchInfo); else,
                    // use folder id/item id combo
                    if (mMessage.mProtocolSearchInfo != null) {
                        s.data(Tags.COMPOSE_LONG_ID, mMessage.mProtocolSearchInfo);
                    } else {
                        s.data(Tags.COMPOSE_ITEM_ID, info.mItemId);
                        s.data(Tags.COMPOSE_FOLDER_ID, info.mCollectionId);
                    }
                    s.end();  // Tags.COMPOSE_SOURCE
                }
            }

            // Start the MIME tag; this is followed by "opaque" data (byte array)
            s.start(Tags.COMPOSE_MIME);
            // Send opaque data from the file stream
            s.opaque(mFileStream, (int)mFileLength);
            // And we're done
            s.end().end().done();
        }
    }

    private static class SendMailParser extends Parser {
        private final int mStartTag;
        private int mStatus;

        public SendMailParser(InputStream in, int startTag) throws IOException {
            super(in);
            mStartTag = startTag;
        }

        public int getStatus() {
            return mStatus;
        }

        /**
         * The only useful info in the SendMail response is the status; we capture and save it
         */
        @Override
        public boolean parse() throws IOException {
            if (nextTag(START_DOCUMENT) != mStartTag) {
                throw new IOException();
            }
            while (nextTag(START_DOCUMENT) != END_DOCUMENT) {
                if (tag == Tags.COMPOSE_STATUS) {
                    mStatus = getValueInt();
                } else {
                    skipTag();
                }
            }
            return true;
        }
    }

    /**
     * For OriginalMessageInfo, we use the terminology of EAS for the serverId and mailboxId of the
     * original message
     */
    protected static class OriginalMessageInfo {
        final String mItemId;
        final String mCollectionId;
        final String mLongId;

        OriginalMessageInfo(String itemId, String collectionId, String longId) {
            mItemId = itemId;
            mCollectionId = collectionId;
            mLongId = longId;
        }
    }

    private void sendCallback(long msgId, String subject, int status) {
        try {
            ExchangeService.callback().sendMessageStatus(msgId, subject, status, 0);
        } catch (RemoteException e) {
            // It's all good
        }
    }

    /*package*/ String generateSmartSendCmd(boolean reply, OriginalMessageInfo info) {
        StringBuilder sb = new StringBuilder();
        sb.append(reply ? "SmartReply" : "SmartForward");
        if (!TextUtils.isEmpty(info.mLongId)) {
            sb.append("&LongId=");
            sb.append(Uri.encode(info.mLongId, ":"));
        } else {
            sb.append("&ItemId=");
            sb.append(Uri.encode(info.mItemId, ":"));
            sb.append("&CollectionId=");
            sb.append(Uri.encode(info.mCollectionId, ":"));
        }
        return sb.toString();
    }

    /**
     * Get information about the original message that is referenced by the message to be sent; this
     * information will exist for replies and forwards
     *
     * @param context the caller's context
     * @param msgId the id of the message we're sending
     * @return a data structure with the serverId and mailboxId of the original message, or null if
     * either or both of those pieces of information can't be found
     */
    private static OriginalMessageInfo getOriginalMessageInfo(Context context, long msgId) {
        // Note: itemId and collectionId are the terms used by EAS to refer to the serverId and
        // mailboxId of a Message
        String itemId = null;
        String collectionId = null;
        String longId = null;

        // First, we need to get the id of the reply/forward message
        String[] cols = Utility.getRowColumns(context, Body.CONTENT_URI,
                BODY_SOURCE_PROJECTION, WHERE_MESSAGE_KEY,
                new String[] {Long.toString(msgId)});
        if (cols != null) {
            long refId = Long.parseLong(cols[0]);
            // Then, we need the serverId and mailboxKey of the message
            cols = Utility.getRowColumns(context, Message.CONTENT_URI, refId,
                    SyncColumns.SERVER_ID, MessageColumns.MAILBOX_KEY,
                    MessageColumns.PROTOCOL_SEARCH_INFO);
            if (cols != null) {
                itemId = cols[0];
                long boxId = Long.parseLong(cols[1]);
                // Then, we need the serverId of the mailbox
                cols = Utility.getRowColumns(context, Mailbox.CONTENT_URI, boxId,
                        MailboxColumns.SERVER_ID);
                if (cols != null) {
                    collectionId = cols[0];
                }
            }
        }
        // We need either a longId or both itemId (serverId) and collectionId (mailboxId) to process
        // a smart reply or a smart forward
        if (longId != null || (itemId != null && collectionId != null)){
            return new OriginalMessageInfo(itemId, collectionId, longId);
        }
        return null;
    }

    private void sendFailed(long msgId, int result) {
        ContentValues cv = new ContentValues();
        cv.put(SyncColumns.SERVER_ID, SEND_FAILED);
        Message.update(mContext, Message.CONTENT_URI, msgId, cv);
        sendCallback(msgId, null, result);
    }

    /**
     * Send a single message via EAS
     * Note that we mark messages SEND_FAILED when there is a permanent failure, rather than an
     * IOException, which is handled by ExchangeService with retries, backoffs, etc.
     *
     * @param cacheDir the cache directory for this context
     * @param msgId the _id of the message to send
     * @throws IOException
     */
    int sendMessage(File cacheDir, long msgId) throws IOException, MessagingException {
        int result;
        // Say we're starting to send this message
        sendCallback(msgId, null, EmailServiceStatus.IN_PROGRESS);
        // Create a temporary file (this will hold the outgoing message in RFC822 (MIME) format)
        File tmpFile = File.createTempFile("eas_", "tmp", cacheDir);
        try {
            // Get the message and fail quickly if not found
            Message msg = Message.restoreMessageWithId(mContext, msgId);
            if (msg == null) return EmailServiceStatus.MESSAGE_NOT_FOUND;

            // See what kind of outgoing messge this is
            int flags = msg.mFlags;
            boolean reply = (flags & Message.FLAG_TYPE_REPLY) != 0;
            boolean forward = (flags & Message.FLAG_TYPE_FORWARD) != 0;
            boolean includeQuotedText = (flags & Message.FLAG_NOT_INCLUDE_QUOTED_TEXT) == 0;

            // The reference message and mailbox are called item and collection in EAS
            OriginalMessageInfo referenceInfo = null;
            // Respect the sense of the include quoted text flag
            if (includeQuotedText && (reply || forward)) {
                referenceInfo = getOriginalMessageInfo(mContext, msgId);
            }
            // Generally, we use SmartReply/SmartForward if we've got a good reference
            boolean smartSend = referenceInfo != null;
            // But we won't use SmartForward if the account isn't set up for it (currently, we only
            // use SmartForward for EAS 12.0 or later to avoid creating eml files that are
            // potentially difficult for the recipient to handle)
            if (forward && ((mAccount.mFlags & Account.FLAGS_SUPPORTS_SMART_FORWARD) == 0)) {
                smartSend = false;
            }

            // Write the message to the temporary file
            FileOutputStream fileOutputStream = new FileOutputStream(tmpFile);
            Rfc822Output.writeTo(mContext, msgId, fileOutputStream, smartSend, true);
            fileOutputStream.close();

            // Sending via EAS14 is a whole 'nother kettle of fish
            boolean isEas14 = (Double.parseDouble(mAccount.mProtocolVersion) >=
                Eas.SUPPORTED_PROTOCOL_EX2010_DOUBLE);

            // Get an input stream to our temporary file and create an entity with it
            FileInputStream fileStream = new FileInputStream(tmpFile);
            long fileLength = tmpFile.length();
            // The type of entity depends on whether we're using EAS 14
            HttpEntity inputEntity;
            // For EAS 14, we need to save the wbxml tag we're using
            int modeTag = 0;
            if (isEas14) {
                int mode = !smartSend ? MODE_NORMAL : reply ? MODE_SMART_REPLY : MODE_SMART_FORWARD;
                modeTag = SendMailEntity.MODE_TAGS[mode];
                inputEntity = new SendMailEntity(mContext, fileStream, fileLength, modeTag, msg);
            } else {
                inputEntity = new InputStreamEntity(fileStream, fileLength);
            }
            // Create the appropriate command and POST it to the server
            String cmd = "SendMail";
            if (smartSend) {
                // In EAS 14, we don't send itemId and collectionId in the command
                if (isEas14) {
                    cmd = reply ? "SmartReply" : "SmartForward";
                } else {
                    cmd = generateSmartSendCmd(reply, referenceInfo);
                }
            }

            // If we're not EAS 14, add our save-in-sent setting here
            if (!isEas14) {
                cmd += "&SaveInSent=T";
            }
            userLog("Send cmd: " + cmd);

            // Finally, post SendMail to the server
            EasResponse resp = sendHttpClientPost(cmd, inputEntity, SEND_MAIL_TIMEOUT);
            try {
                fileStream.close();
                int code = resp.getStatus();
                if (code == HttpStatus.SC_OK) {
                    // HTTP OK before EAS 14 is a thumbs up; in EAS 14, we've actually got to parse
                    // the reply
                    if (isEas14) {
                        try {
                            // Try to parse the result
                            SendMailParser p = new SendMailParser(resp.getInputStream(), modeTag);
                            // If we get here, the SendMail failed; go figure
                            p.parse();
                            // The parser holds the status
                            int status = p.getStatus();
                            userLog("SendMail error, status: " + status);
                            // The only "interesting" failure is a security error.  Note that an
                            // auth error would have manifest with an HTTP error code
                            if (CommandStatus.isNeedsProvisioning(status)) {
                                result = EmailServiceStatus.SECURITY_FAILURE;
                            } else {
                                // We mark the result as SUCCESS on a non-security failure since the
                                // message itself will be marked failed and we don't want to block
                                // other messages
                                result = EmailServiceStatus.SUCCESS;
                            }
                            sendFailed(msgId, result);
                            return result;
                        } catch (EmptyStreamException e) {
                            // This is actually fine; an empty stream means SendMail succeeded
                        }
                    }

                    // If we're here, the SendMail command succeeded
                    userLog("Deleting message...");
                    // Delete the message from the Outbox and send callback
                    mContentResolver.delete(ContentUris.withAppendedId(Message.CONTENT_URI, msgId),
                            null, null);
                    result = EmailServiceStatus.SUCCESS;
                    sendCallback(-1, msg.mSubject, EmailServiceStatus.SUCCESS);
                } else {
                    userLog("Message sending failed, code: " + code);
                    if (EasResponse.isAuthError(code)) {
                        result = EmailServiceStatus.LOGIN_FAILED;
                    } else {
                        // We mark the result as SUCCESS on a non-auth failure since the message
                        // itself will be marked failed and we don't want to block other messages
                        result = EmailServiceStatus.SUCCESS;
                    }
                    sendFailed(msgId, result);
                }
            } finally {
                resp.close();
            }
        } catch (IOException e) {
            // We catch this just to send the callback
            sendCallback(msgId, null, EmailServiceStatus.CONNECTION_ERROR);
            throw e;
        } finally {
            // Clean up the temporary file
            if (tmpFile.exists()) {
                tmpFile.delete();
            }
        }
        return result;
    }

    @Override
    public void run() {
        setupService();
        // Use SMTP flags for sending mail
        TrafficStats.setThreadStatsTag(TrafficFlags.getSmtpFlags(mContext, mAccount));
        File cacheDir = mContext.getCacheDir();
        try {
            mDeviceId = ExchangeService.getDeviceId(mContext);
            // Get a cursor to Outbox messages
            Cursor c = mContext.getContentResolver().query(Message.CONTENT_URI,
                    Message.ID_COLUMN_PROJECTION, MAILBOX_KEY_AND_NOT_SEND_FAILED,
                    new String[] {Long.toString(mMailbox.mId)}, null);
            try {
                // Loop through the messages, sending each one
                while (c.moveToNext()) {
                    long msgId = c.getLong(Message.ID_COLUMNS_ID_COLUMN);
                    if (msgId != 0) {
                        if (Utility.hasUnloadedAttachments(mContext, msgId)) {
                            // We'll just have to wait on this...
                            continue;
                        }
                        int result = sendMessage(cacheDir, msgId);
                        // If there's an error, it should stop the service; we will distinguish
                        // at least between login failures and everything else
                        if (result == EmailServiceStatus.LOGIN_FAILED) {
                            mExitStatus = EXIT_LOGIN_FAILURE;
                            return;
                        } else if (result == EmailServiceStatus.SECURITY_FAILURE) {
                            mExitStatus = EXIT_SECURITY_FAILURE;
                            return;
                        } else if (result == EmailServiceStatus.REMOTE_EXCEPTION) {
                            mExitStatus = EXIT_EXCEPTION;
                            return;
                        }
                    }
                }
            } finally {
                c.close();
            }
            mExitStatus = EXIT_DONE;
        } catch (IOException e) {
            mExitStatus = EXIT_IO_ERROR;
        } catch (Exception e) {
            userLog("Exception caught in EasOutboxService", e);
            mExitStatus = EXIT_EXCEPTION;
        } finally {
            userLog(mMailbox.mDisplayName, ": sync finished");
            userLog("Outbox exited with status ", mExitStatus);
            ExchangeService.done(this);
        }
    }

    /**
     * Convenience method for adding a Message to an account's outbox
     * @param context the context of the caller
     * @param accountId the accountId for the sending account
     * @param msg the message to send
     */
    public static void sendMessage(Context context, long accountId, Message msg) {
        Mailbox mailbox = Mailbox.restoreMailboxOfType(context, accountId, Mailbox.TYPE_OUTBOX);
        if (mailbox != null) {
            msg.mMailboxKey = mailbox.mId;
            msg.mAccountKey = accountId;
            msg.save(context);
        }
    }
}