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");
                return RESULT_OK;
            } 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();
        }
    }
}
