/*
 * Copyright (C) 2014 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.eas;

import android.content.Context;
import android.os.RemoteException;

import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.provider.EmailContent.Attachment;
import com.android.emailcommon.service.EmailServiceStatus;
import com.android.emailcommon.service.IEmailServiceCallback;
import com.android.emailcommon.utility.AttachmentUtilities;
import com.android.exchange.Eas;
import com.android.exchange.EasResponse;
import com.android.exchange.adapter.ItemOperationsParser;
import com.android.exchange.adapter.Serializer;
import com.android.exchange.adapter.Tags;
import com.android.exchange.service.EasService;
import com.android.exchange.utility.UriCodec;
import com.android.mail.utils.LogUtils;

import org.apache.http.HttpEntity;

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

/**
 * This class performs the heavy lifting of loading attachments from the Exchange server to the
 * device in a local file.
 * TODO: Add ability to call back to UI when this failed, and generally better handle error cases.
 */
public final class EasLoadAttachment extends EasOperation {

    public static final int RESULT_SUCCESS = 0;

    /** Attachment Loading Errors **/
    public static final int RESULT_LOAD_ATTACHMENT_INFO_ERROR = -100;
    public static final int RESULT_ATTACHMENT_NO_LOCATION_ERROR = -101;
    public static final int RESULT_ATTACHMENT_LOAD_MESSAGE_ERROR = -102;
    public static final int RESULT_ATTACHMENT_INTERNAL_HANDLING_ERROR = -103;
    public static final int RESULT_ATTACHMENT_RESPONSE_PARSING_ERROR = -104;

    private final IEmailServiceCallback mCallback;
    private final long mAttachmentId;

    // These members are set in a future point in time outside of the constructor.
    private Attachment mAttachment;

    /**
     * Constructor for use with {@link EasService} when performing an actual sync.
     * @param context Our {@link Context}.
     * @param accountId The id of the account in question (i.e. its id in the database).
     * @param attachmentId The local id of the attachment (i.e. its id in the database).
     * @param callback The callback for any status updates.
     */
    public EasLoadAttachment(final Context context, final long accountId, final long attachmentId,
            final IEmailServiceCallback callback) {
        // The account is loaded before performOperation but it is not guaranteed to be available
        // before then.
        super(context, accountId);
        mCallback = callback;
        mAttachmentId = attachmentId;
    }

    /**
     * Helper function that makes a callback for us within our implementation.
     */
    private static void doStatusCallback(final IEmailServiceCallback callback,
            final long messageKey, final long attachmentId, final int status, final int progress) {
        if (callback != null) {
            try {
                // loadAttachmentStatus is mart of IEmailService interface.
                callback.loadAttachmentStatus(messageKey, attachmentId, status, progress);
            } catch (final RemoteException e) {
                LogUtils.e(LOG_TAG, "RemoteException in loadAttachment: %s", e.getMessage());
            }
        }
    }

    /**
     * Helper class that is passed to other objects to perform callbacks for us.
     */
    public static class ProgressCallback {
        private final IEmailServiceCallback mCallback;
        private final EmailContent.Attachment mAttachment;

        public ProgressCallback(final IEmailServiceCallback callback,
                final EmailContent.Attachment attachment) {
            mCallback = callback;
            mAttachment = attachment;
        }

        public void doCallback(final int progress) {
            doStatusCallback(mCallback, mAttachment.mMessageKey, mAttachment.mId,
                    EmailServiceStatus.IN_PROGRESS, progress);
        }
    }

    /**
     * Encoder for Exchange 2003 attachment names.  They come from the server partially encoded,
     * but there are still possible characters that need to be encoded (Why, MSFT, why?)
     */
    private static class AttachmentNameEncoder extends UriCodec {
        @Override
        protected boolean isRetained(final char c) {
            // These four characters are commonly received in EAS 2.5 attachment names and are
            // valid (verified by testing); we won't encode them
            return c == '_' || c == ':' || c == '/' || c == '.';
        }
    }

    /**
     * Finish encoding attachment names for Exchange 2003.
     * @param str A partially encoded string.
     * @return The fully encoded version of str.
     */
    private static String encodeForExchange2003(final String str) {
        final AttachmentNameEncoder enc = new AttachmentNameEncoder();
        final StringBuilder sb = new StringBuilder(str.length() + 16);
        enc.appendPartiallyEncoded(sb, str);
        return sb.toString();
    }

    /**
     * Finish encoding attachment names for Exchange 2003.
     * @return A {@link EmailServiceStatus} code that indicates the result of the operation.
     */
    @Override
    public int performOperation() {
        mAttachment = EmailContent.Attachment.restoreAttachmentWithId(mContext, mAttachmentId);
        if (mAttachment == null) {
            LogUtils.e(LOG_TAG, "Could not load attachment %d", mAttachmentId);
            doStatusCallback(mCallback, -1, mAttachmentId, EmailServiceStatus.ATTACHMENT_NOT_FOUND,
                    0);
            return RESULT_LOAD_ATTACHMENT_INFO_ERROR;
        }
        if (mAttachment.mLocation == null) {
            LogUtils.e(LOG_TAG, "Attachment %d lacks a location", mAttachmentId);
            doStatusCallback(mCallback, -1, mAttachmentId, EmailServiceStatus.ATTACHMENT_NOT_FOUND,
                    0);
            return RESULT_ATTACHMENT_NO_LOCATION_ERROR;
        }
        final EmailContent.Message message = EmailContent.Message
                .restoreMessageWithId(mContext, mAttachment.mMessageKey);
        if (message == null) {
            LogUtils.e(LOG_TAG, "Could not load message %d", mAttachment.mMessageKey);
            doStatusCallback(mCallback, mAttachment.mMessageKey, mAttachmentId,
                    EmailServiceStatus.MESSAGE_NOT_FOUND, 0);
            return RESULT_ATTACHMENT_LOAD_MESSAGE_ERROR;
        }

        // First callback to let the client know that we have started the attachment load.
        doStatusCallback(mCallback, mAttachment.mMessageKey, mAttachmentId,
                EmailServiceStatus.IN_PROGRESS, 0);

        final int result = super.performOperation();

        // Last callback to report results.
        if (result < 0) {
            // We had an error processing an attachment, let's report a {@link EmailServiceStatus}
            // connection error in this case
            LogUtils.d(LOG_TAG, "Invoking callback for attachmentId: %d with CONNECTION_ERROR",
                    mAttachmentId);
            doStatusCallback(mCallback, mAttachment.mMessageKey, mAttachmentId,
                    EmailServiceStatus.CONNECTION_ERROR, 0);
        } else {
            LogUtils.d(LOG_TAG, "Invoking callback for attachmentId: %d with SUCCESS",
                    mAttachmentId);
            doStatusCallback(mCallback, mAttachment.mMessageKey, mAttachmentId,
                    EmailServiceStatus.SUCCESS, 0);
        }
        return result;
    }

    @Override
    protected String getCommand() {
        if (mAttachment == null) {
            LogUtils.wtf(LOG_TAG, "Error, mAttachment is null");
        }

        final String cmd;
        if (getProtocolVersion() >= Eas.SUPPORTED_PROTOCOL_EX2010_DOUBLE) {
            // The operation is different in EAS 14.0 than in earlier versions
            cmd = "ItemOperations";
        } else {
            final String location;
            // For Exchange 2003 (EAS 2.5), we have to look for illegal chars in the file name
            // that EAS sent to us!
            if (getProtocolVersion() < Eas.SUPPORTED_PROTOCOL_EX2007_DOUBLE) {
                location = encodeForExchange2003(mAttachment.mLocation);
            } else {
                location = mAttachment.mLocation;
            }
            cmd = "GetAttachment&AttachmentName=" + location;
        }
        return cmd;
    }

    @Override
    protected HttpEntity getRequestEntity() throws IOException {
        if (mAttachment == null) {
            LogUtils.wtf(LOG_TAG, "Error, mAttachment is null");
        }

        final HttpEntity entity;
        final Serializer s = new Serializer();
        if (getProtocolVersion() >= Eas.SUPPORTED_PROTOCOL_EX2010_DOUBLE) {
            s.start(Tags.ITEMS_ITEMS).start(Tags.ITEMS_FETCH);
            s.data(Tags.ITEMS_STORE, "Mailbox");
            s.data(Tags.BASE_FILE_REFERENCE, mAttachment.mLocation);
            s.end().end().done(); // ITEMS_FETCH, ITEMS_ITEMS
            entity = makeEntity(s);
        } else {
            // Older versions of the protocol have the attachment location in the command.
            entity = null;
        }
        return entity;
    }

    /**
     * Close, ignoring errors (as during cleanup)
     * @param c a Closeable
     */
    private static void close(final Closeable c) {
        try {
            c.close();
        } catch (IOException e) {
            LogUtils.e(LOG_TAG, "IOException while cleaning up attachment: %s", e.getMessage());
        }
    }

    /**
     * Save away the contentUri for this Attachment and notify listeners
     */
    private boolean finishLoadAttachment(final EmailContent.Attachment attachment, final File file) {
        final InputStream in;
        try {
            in = new FileInputStream(file);
        } catch (final FileNotFoundException e) {
            // Unlikely, as we just created it successfully, but log it.
            LogUtils.e(LOG_TAG, "Could not open attachment file: %s", e.getMessage());
            return false;
        }
        AttachmentUtilities.saveAttachment(mContext, in, attachment);
        close(in);
        return true;
    }

    /**
     * Read the {@link EasResponse} and extract the attachment data, saving it to the provider.
     * @param response The (successful) {@link EasResponse} containing the attachment data.
     * @return A status code, 0 is a success, anything negative is an error outlined by constants
     *         in this class or its base class.
     */
    @Override
    protected int handleResponse(final EasResponse response) {
        // Some very basic error checking on the response object first.
        // Our base class should be responsible for checking these errors but if the error
        // checking is done in the override functions, we can be more specific about
        // the errors that are being returned to the caller of performOperation().
        if (response.isEmpty()) {
            LogUtils.e(LOG_TAG, "Error, empty response.");
            return RESULT_REQUEST_FAILURE;
        }

        // This is a 2 step process.
        // 1. Grab what came over the wire and write it to a temp file on disk.
        // 2. Move the attachment to its final location.
        final File tmpFile;
        try {
            tmpFile = File.createTempFile("eas_", "tmp", mContext.getCacheDir());
        } catch (final IOException e) {
            LogUtils.e(LOG_TAG, "Could not open temp file: %s", e.getMessage());
            return RESULT_REQUEST_FAILURE;
        }

        try {
            final OutputStream os;
            try {
                os = new FileOutputStream(tmpFile);
            } catch (final FileNotFoundException e) {
                LogUtils.e(LOG_TAG, "Temp file not found: %s", e.getMessage());
                return RESULT_ATTACHMENT_INTERNAL_HANDLING_ERROR;
            }
            try {
                final InputStream is = response.getInputStream();
                try {
                    // TODO: Right now we are explictly loading this from a class
                    // that will be deprecated when we move over to EasService. When we start using
                    // our internal class instead, there will be rippling side effect changes that
                    // need to be made when this time comes.
                    final ProgressCallback callback = new ProgressCallback(mCallback, mAttachment);
                    final boolean success;
                    if (getProtocolVersion() >= Eas.SUPPORTED_PROTOCOL_EX2010_DOUBLE) {
                        final ItemOperationsParser parser = new ItemOperationsParser(is, os,
                                mAttachment.mSize, callback);
                        parser.parse();
                        success = (parser.getStatusCode() == 1);
                    } else {
                        final int length = response.getLength();
                        if (length != 0) {
                            // len > 0 means that Content-Length was set in the headers
                            // len < 0 means "chunked" transfer-encoding
                            ItemOperationsParser.readChunked(is, os,
                                    (length < 0) ? mAttachment.mSize : length, callback);
                        }
                        success = true;
                    }
                    // Check that we successfully grabbed what came over the wire...
                    if (!success) {
                        LogUtils.e(LOG_TAG, "Error parsing server response");
                        return RESULT_ATTACHMENT_RESPONSE_PARSING_ERROR;
                    }
                    // Now finish the process and save to the final destination.
                    final boolean loadResult = finishLoadAttachment(mAttachment, tmpFile);
                    if (!loadResult) {
                        LogUtils.e(LOG_TAG, "Error post processing attachment file.");
                        return RESULT_ATTACHMENT_INTERNAL_HANDLING_ERROR;
                    }
                } catch (final IOException e) {
                    LogUtils.e(LOG_TAG, "Error handling attachment: %s", e.getMessage());
                    return RESULT_ATTACHMENT_INTERNAL_HANDLING_ERROR;
                } finally {
                    close(is);
                }
            } finally {
                close(os);
            }
        } finally {
            tmpFile.delete();
        }
        return RESULT_SUCCESS;
    }
}
