/*
 * 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 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.Attachment;
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.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;

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;

    protected 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() {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            try {
                // Calculate the overhead for the WBXML data
                writeTo(baos, false);
                // Return the actual size that will be sent
                return baos.size() + mFileLength;
            } catch (IOException e) {
                // Just return -1 (unknown)
            } finally {
                try {
                    baos.close();
                } catch (IOException e) {
                    // Ignore
                }
            }
            return -1;
        }

        @Override
        public void writeTo(OutputStream outstream) throws IOException {
            writeTo(outstream, true);
        }

        /**
         * Write the message to the output stream
         * @param outstream the output stream to write
         * @param withData whether or not the actual data is to be written; true when sending
         *   mail; false when calculating size only
         * @throws IOException
         */
        public void writeTo(OutputStream outstream, boolean withData) 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
            if (withData) {
                s.opaque(mFileStream, (int)mFileLength);
            } else {
                s.opaqueWithoutData((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 long mRefId;
        final String mItemId;
        final String mCollectionId;

        OriginalMessageInfo(long refId, String itemId, String collectionId) {
            mRefId = refId;
            mItemId = itemId;
            mCollectionId = collectionId;
        }
    }

    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");
        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;

        // 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)});
        long refId = 0;
        if (cols != null) {
            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 (itemId != null && collectionId != null){
            return new OriginalMessageInfo(refId, itemId, collectionId);
        }
        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);
    }

    /**
     * See if a given attachment is among an array of attachments; it is if the locations of both
     * are the same (we're looking to see if they represent the same attachment on the server. Note
     * that an attachment that isn't on the server (e.g. an outbound attachment picked from the
     * gallery) won't have a location, so the result will always be false
     *
     * @param att the attachment to test
     * @param atts the array of attachments to look in
     * @return whether the test attachment is among the array of attachments
     */
    private boolean amongAttachments(Attachment att, Attachment[] atts) {
        String location = att.mLocation;
        if (location == null) return false;
        for (Attachment a: atts) {
            if (location.equals(a.mLocation)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 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 {
        // We always return SUCCESS unless the sending error is account-specific (security or
        // authentication) rather than message-specific; returning anything else will terminate
        // the Outbox sync! Message-specific errors are marked in the messages themselves.
        int result = EmailServiceStatus.SUCCESS;
        // 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;
            }

            ArrayList<Attachment> requiredAtts = null;
            if (smartSend && forward) {
                // See if we can really smart forward (all reference attachments must be sent)
                Attachment[] outAtts =
                        Attachment.restoreAttachmentsWithMessageId(mContext, msg.mId);
                Attachment[] refAtts =
                        Attachment.restoreAttachmentsWithMessageId(mContext, referenceInfo.mRefId);
                for (Attachment refAtt: refAtts) {
                    // If an original attachment isn't among what's going out, we can't be "smart"
                    if (!amongAttachments(refAtt, outAtts)) {
                        smartSend = false;
                        break;
                    }
                }
                if (smartSend) {
                    requiredAtts = new ArrayList<Attachment>();
                    for (Attachment outAtt: outAtts) {
                        // If an outgoing attachment isn't in original message, we must send it
                        if (!amongAttachments(outAtt, refAtts)) {
                            requiredAtts.add(outAtt);
                        }
                    }
                }
            }

            // Write the message to the temporary file
            FileOutputStream fileOutputStream = new FileOutputStream(tmpFile);
            // If we're using smartSend, send along our required attachments (which will be empty
            // if the user hasn't added new ones); otherwise, null to send everything in the msg
            Rfc822Output.writeTo(mContext, msgId, fileOutputStream, smartSend, true,
                    smartSend ? requiredAtts : null);
            fileOutputStream.close();

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

            while (true) {
                // 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 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);
                                if (CommandStatus.isNeedsProvisioning(status)) {
                                    result = EmailServiceStatus.SECURITY_FAILURE;
                                } else if (status == CommandStatus.ITEM_NOT_FOUND && smartSend) {
                                    // This is the retry case for EAS 14; we'll send without "smart"
                                    // commands next time
                                    resp.close();
                                    smartSend = false;
                                    continue;
                                }
                                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);
                        sendCallback(-1, msg.mSubject, EmailServiceStatus.SUCCESS);
                        break;
                    } else if (code == EasSyncService.INTERNAL_SERVER_ERROR_CODE && smartSend) {
                        // This is the retry case for EAS 12.1 and below; we'll send without "smart"
                        // commands next time
                        resp.close();
                        smartSend = false;
                    } else {
                        userLog("Message sending failed, code: " + code);
                        if (EasResponse.isAuthError(code)) {
                            result = EmailServiceStatus.LOGIN_FAILED;
                        } else if (EasResponse.isProvisionError(code)) {
                            result = EmailServiceStatus.SECURITY_FAILURE;
                        }
                        sendFailed(msgId, result);
                        break;
                    }
                } 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);
        }
    }
}