package com.android.exchange.eas;

import android.content.ContentUris;
import android.content.Context;
import android.net.Uri;
import android.text.format.DateUtils;
import android.util.Log;

import com.android.emailcommon.internet.Rfc822Output;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.Mailbox;
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.utility.Utility;
import com.android.exchange.CommandStatusException;
import com.android.exchange.Eas;
import com.android.exchange.EasResponse;
import com.android.exchange.CommandStatusException.CommandStatus;
import com.android.exchange.adapter.SendMailParser;
import com.android.exchange.adapter.Serializer;
import com.android.exchange.adapter.Tags;
import com.android.exchange.adapter.Parser.EmptyStreamException;
import com.android.mail.utils.LogUtils;

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.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;

public class EasOutboxSync extends EasOperation {

    // Value for a message's server id when sending fails.
    public static final int SEND_FAILED = 1;
    // 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 long SEND_MAIL_TIMEOUT = 15 * DateUtils.MINUTE_IN_MILLIS;

    public static final int RESULT_OK = 1;
    public static final int RESULT_IO_ERROR = -100;
    public static final int RESULT_ITEM_NOT_FOUND = -101;
    public static final int RESULT_SEND_FAILED = -102;

    private final Message mMessage;
    private final boolean mIsEas14;
    private final File mCacheDir;
    private final SmartSendInfo mSmartSendInfo;
    private final int mModeTag;
    private File mTmpFile;
    private FileInputStream mFileStream;

    public EasOutboxSync(final Context context, final Account account, final Message message,
            final boolean useSmartSend) {
        super(context, account);
        mMessage = message;
        mIsEas14 = (Double.parseDouble(mAccount.mProtocolVersion) >=
                Eas.SUPPORTED_PROTOCOL_EX2010_DOUBLE);
        mCacheDir = context.getCacheDir();
        if (useSmartSend) {
            mSmartSendInfo = SmartSendInfo.getSmartSendInfo(mContext, mAccount, mMessage);
        } else {
            mSmartSendInfo = null;
        }
        mModeTag = getModeTag(mSmartSendInfo);
    }

    @Override
    protected String getCommand() {
        String cmd = "SendMail";
        if (mSmartSendInfo != null) {
            // In EAS 14, we don't send itemId and collectionId in the command
            if (mIsEas14) {
                cmd = mSmartSendInfo.isForward() ? "SmartForward" : "SmartReply";
            } else {
                cmd = mSmartSendInfo.generateSmartSendCmd();
            }
        }
        // If we're not EAS 14, add our save-in-sent setting here
        if (!mIsEas14) {
            cmd += "&SaveInSent=T";
        }
        return cmd;
    }

    @Override
    protected HttpEntity getRequestEntity() throws IOException {
        try {
            mTmpFile = File.createTempFile("eas_", "tmp", mCacheDir);
        } catch (final IOException e) {
            LogUtils.w(LOG_TAG, "IO error creating temp file");
            throw new IllegalStateException("Failure creating temp file");
        }

        if (!writeMessageToTempFile(mTmpFile, mMessage, mSmartSendInfo)) {
            LogUtils.w(LOG_TAG, "IO error writing to temp file");
            throw new IllegalStateException("Failure writing to temp file");
        }

        try {
            mFileStream = new FileInputStream(mTmpFile);
        } catch (final FileNotFoundException e) {
            LogUtils.w(LOG_TAG, "IO error creating fileInputStream");
            throw new IllegalStateException("Failure creating fileInputStream");
        }
          final long fileLength = mTmpFile.length();
          final HttpEntity entity;
          if (mIsEas14) {
              entity = new SendMailEntity(mFileStream, fileLength, mModeTag, mMessage,
                      mSmartSendInfo);
          } else {
              entity = new InputStreamEntity(mFileStream, fileLength);
          }

          return entity;
    }

    @Override
    protected int handleHttpError(int httpStatus) {
        if (httpStatus == HttpStatus.SC_INTERNAL_SERVER_ERROR && mSmartSendInfo != null) {
            // Let's retry without "smart" commands.
            return RESULT_ITEM_NOT_FOUND;
        } else {
            return RESULT_OTHER_FAILURE;
        }
    }

    @Override
    protected void onRequestMade() {
        try {
            mFileStream.close();
        } catch (IOException e) {
            LogUtils.w(LOG_TAG, "IOException closing fileStream %s", e);
        }
        if (mTmpFile != null && mTmpFile.exists()) {
            mTmpFile.delete();
        }
    }

    @Override
    protected int handleResponse(EasResponse response) throws IOException, CommandStatusException {
        if (mIsEas14) {
            try {
                // Try to parse the result
                final SendMailParser p = new SendMailParser(response.getInputStream(), mModeTag);
                // If we get here, the SendMail failed; go figure
                p.parse();
                // The parser holds the status
                final int status = p.getStatus();
                if (CommandStatus.isNeedsProvisioning(status)) {
                    LogUtils.w(LOG_TAG, "Needs provisioning sending mail");
                    return RESULT_PROVISIONING_ERROR;
                } else if (status == CommandStatus.ITEM_NOT_FOUND &&
                        mSmartSendInfo != null) {
                    // Let's retry without "smart" commands.
                    LogUtils.w(LOG_TAG, "Needs provisioning sending mail");
                    return RESULT_ITEM_NOT_FOUND;
                }

                // TODO: Set syncServerId = SEND_FAILED in DB?
                LogUtils.d(LOG_TAG, "General failure sending mail");
                return RESULT_SEND_FAILED;
            } catch (final EmptyStreamException e) {
                // This is actually fine; an empty stream means SendMail succeeded
                LogUtils.d(LOG_TAG, "empty response sending mail");
                // Don't return here, fall through so that we'll delete the sent message.
            } catch (final IOException e) {
                // Parsing failed in some other way.
                LogUtils.w(LOG_TAG, "IOException sending mail");
                return RESULT_IO_ERROR;
            }
        } else {
            // FLAG: Do we need to parse results for earlier versions?
        }
        mContext.getContentResolver().delete(
            ContentUris.withAppendedId(Message.CONTENT_URI, mMessage.mId), null, null);
        return RESULT_OK;
    }

    /**
     * Writes message to the temp file.
     * @param tmpFile The temp file to use.
     * @param message The {@link Message} to write.
     * @param smartSendInfo The {@link SmartSendInfo} for this message send attempt.
     * @return Whether we could successfully write the file.
     */
    private boolean writeMessageToTempFile(final File tmpFile, final Message message,
            final SmartSendInfo smartSendInfo) {
        final FileOutputStream fileStream;
        try {
            fileStream = new FileOutputStream(tmpFile);
            Log.d(LogUtils.TAG, "created outputstream");
        } catch (final FileNotFoundException e) {
            Log.e(LogUtils.TAG, "Failed to create message file", e);
            return false;
        }
        try {
            final boolean smartSend = smartSendInfo != null;
            final ArrayList<Attachment> attachments =
                    smartSend ? smartSendInfo.mRequiredAtts : null;
            Rfc822Output.writeTo(mContext, message, fileStream, smartSend, true, attachments);
        } catch (final Exception e) {
            Log.e(LogUtils.TAG, "Failed to write message file", e);
            return false;
        } finally {
            try {
                fileStream.close();
            } catch (final IOException e) {
                // should not happen
                Log.e(LogUtils.TAG, "Failed to close file - should not happen", e);
            }
        }
        return true;
    }

    private int getModeTag(final SmartSendInfo smartSendInfo) {
        if (mIsEas14) {
            if (smartSendInfo == null) {
                return Tags.COMPOSE_SEND_MAIL;
            } else if (smartSendInfo.isForward()) {
                return Tags.COMPOSE_SMART_FORWARD;
            } else {
                return Tags.COMPOSE_SMART_REPLY;
            }
        }
        return 0;
    }

    /**
     * Information needed for SmartReply/SmartForward.
     */
    private static class SmartSendInfo {
        public static final String[] BODY_SOURCE_PROJECTION =
                new String[] {BodyColumns.SOURCE_MESSAGE_KEY};
        public static final String WHERE_MESSAGE_KEY = Body.MESSAGE_KEY + "=?";

        final String mItemId;
        final String mCollectionId;
        final boolean mIsReply;
        final ArrayList<Attachment> mRequiredAtts;

        private SmartSendInfo(final String itemId, final String collectionId,
                final boolean isReply,ArrayList<Attachment> requiredAtts) {
            mItemId = itemId;
            mCollectionId = collectionId;
            mIsReply = isReply;
            mRequiredAtts = requiredAtts;
        }

        public String generateSmartSendCmd() {
            final StringBuilder sb = new StringBuilder();
            sb.append(isForward() ? "SmartForward" : "SmartReply");
            sb.append("&ItemId=");
            sb.append(Uri.encode(mItemId, ":"));
            sb.append("&CollectionId=");
            sb.append(Uri.encode(mCollectionId, ":"));
            return sb.toString();
        }

        public boolean isForward() {
            return !mIsReply;
        }

        /**
         * 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 static boolean amongAttachments(final Attachment att, final Attachment[] atts) {
            final String location = att.mLocation;
            if (location == null) return false;
            for (final Attachment a: atts) {
                if (location.equals(a.mLocation)) {
                    return true;
                }
            }
            return false;
        }

        /**
         * If this message should use SmartReply or SmartForward, return an object with the data
         * for the smart send.
         *
         * @param context the caller's context
         * @param account the Account we're sending from
         * @param message the Message being sent
         * @return an object to support smart sending, or null if not applicable.
         */
        public static SmartSendInfo getSmartSendInfo(final Context context,
                final Account account, final Message message) {
            final int flags = message.mFlags;
            // We only care about the original message if we include quoted text.
            if ((flags & Message.FLAG_NOT_INCLUDE_QUOTED_TEXT) != 0) {
                return null;
            }
            final boolean reply = (flags & Message.FLAG_TYPE_REPLY) != 0;
            final boolean forward = (flags & Message.FLAG_TYPE_FORWARD) != 0;
            // We also only care for replies or forwards.
            if (!reply && !forward) {
                return null;
            }
            // Just a sanity check here, since we assume that reply and forward are mutually
            // exclusive throughout this class.
            if (reply && forward) {
                return null;
            }
            // If we don't support SmartForward and it's a forward, then don't proceed.
            if (forward && (account.mFlags & Account.FLAGS_SUPPORTS_SMART_FORWARD) == 0) {
                return null;
            }

            // 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(message.mId)});
            long refId = 0;
            // TODO: We can probably just write a smarter query to do this all at once.
            if (cols != null && cols[0] != 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];
                    final 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) {
                final ArrayList<Attachment> requiredAtts;
                if (forward) {
                    // See if we can really smart forward (all reference attachments must be sent)
                    final Attachment[] outAtts =
                            Attachment.restoreAttachmentsWithMessageId(context, message.mId);
                    final Attachment[] refAtts =
                            Attachment.restoreAttachmentsWithMessageId(context, refId);
                    for (final Attachment refAtt: refAtts) {
                        // If an original attachment isn't among what's going out, we can't be smart
                        if (!amongAttachments(refAtt, outAtts)) {
                            return null;
                        }
                    }
                    requiredAtts = new ArrayList<Attachment>();
                    for (final Attachment outAtt: outAtts) {
                        // If an outgoing attachment isn't in original message, we must send it
                        if (!amongAttachments(outAtt, refAtts)) {
                            requiredAtts.add(outAtt);
                        }
                    }
                } else {
                    requiredAtts = null;
                }
                return new SmartSendInfo(itemId, collectionId, reply, requiredAtts);
            }
            return null;
        }
    }

    /**
     * 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 FileInputStream mFileStream;
        private final long mFileLength;
        private final int mSendTag;
        private final Message mMessage;
        private final SmartSendInfo mSmartSendInfo;

        public SendMailEntity(final FileInputStream instream, final long length, final int tag,
                final Message message, final SmartSendInfo smartSendInfo) {
            super(instream, length);
            mFileStream = instream;
            mFileLength = length;
            mSendTag = tag;
            mMessage = message;
            mSmartSendInfo = smartSendInfo;
        }

        /**
         * 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() {
            final 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 (final IOException e) {
                // Just return -1 (unknown)
            } finally {
                try {
                    baos.close();
                } catch (final IOException e) {
                    // Ignore
                }
            }
            return -1;
        }

        @Override
        public void writeTo(final 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(final OutputStream outstream, final 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
            final 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) {
                if (mSmartSendInfo != 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, mSmartSendInfo.mItemId);
                        s.data(Tags.COMPOSE_FOLDER_ID, mSmartSendInfo.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();
        }
    }
}
