/*
 * 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 {

    /** 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.
        LogUtils.e(LOG_TAG, "Calling callback for %d with IN_PROGRESS", mAttachmentId);
        doStatusCallback(mCallback, mAttachment.mMessageKey, mAttachmentId,
                EmailServiceStatus.IN_PROGRESS, 0);

        final int return_value = super.performOperation();

        // Last callback to report results.
        if (return_value < 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 return_value;
    }

    @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 0;
    }
}
