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

import android.content.ContentResolver;
import android.content.Context;
import android.content.SyncResult;
import android.net.TrafficStats;
import android.os.Bundle;
import android.text.format.DateUtils;

import com.android.emailcommon.TrafficFlags;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.Mailbox;
import com.android.exchange.CommandStatusException;
import com.android.exchange.Eas;
import com.android.exchange.EasResponse;
import com.android.exchange.adapter.AbstractSyncParser;
import com.android.exchange.adapter.Parser;
import com.android.exchange.adapter.Serializer;
import com.android.exchange.adapter.Tags;
import com.android.exchange.eas.EasProvision;
import com.android.mail.utils.LogUtils;

import org.apache.http.HttpStatus;

import java.io.IOException;
import java.io.InputStream;
import java.security.cert.CertificateException;

/**
 * Base class for syncing a single collection from an Exchange server. A "collection" is a single
 * mailbox, or contacts for an account, or calendar for an account. (Tasks is part of the protocol
 * but not implemented.)
 * A single {@link ContentResolver#requestSync} for a single collection corresponds to a single
 * object (of the appropriate subclass) being created and {@link #performSync} being called on it.
 * This in turn will result in one or more Sync POST requests being sent to the Exchange server;
 * from the client's point of view, these multiple Exchange Sync requests are all part of the same
 * "sync" (i.e. the fact that there are multiple requests to the server is a detail of the Exchange
 * protocol).
 * Different collection types (e.g. mail, contacts, calendar) should subclass this class and
 * implement the various abstract functions. The majority of how the sync flow is common to all,
 * aside from a few details and the {@link Parser} used.
 * Details on how this class (and Exchange Sync) works:
 * - Overview MSDN link: http://msdn.microsoft.com/en-us/library/ee159766(v=exchg.80).aspx
 * - Sync MSDN link: http://msdn.microsoft.com/en-us/library/gg675638(v=exchg.80).aspx
 * - The very first time, the client sends a Sync request with SyncKey = 0 and no other parameters.
 *   This initial Sync request simply gets us a real SyncKey.
 *   TODO: We should add the initial Sync to EasAccountSyncHandler.
 * - Non-initial Sync requests can be for one or more collections; this implementation does one at
 *   a time. TODO: allow sync for multiple collections to be aggregated?
 * - For each collection, we send SyncKey, ServerId, other modifiers, Options, and Commands. The
 *   protocol has a specific order in which these elements must appear in the request.
 * - {@link #buildEasRequest} forms the XML for the request, using {@link #setInitialSyncOptions},
 *   {@link #setNonInitialSyncOptions}, and {@link #setUpsyncCommands} to fill in the details
 *   specific for each collection type.
 * - The Sync response may specify that there's more data available on the server, in which case
 *   we keep sending Sync requests to get that data.
 * - The ordering constraints and other details may require subclasses to have member variables to
 *   store state between the various calls while performing a single Sync request. These may need
 *   to be reset between Sync requests to the Exchange server. Additionally, there are possibly
 *   other necessary cleanups after parsing a Sync response. These are handled in {@link #cleanup}.
 */
public abstract class EasSyncHandler extends EasServerConnection {
    private static final String TAG = Eas.LOG_TAG;

    public static final int MAX_WINDOW_SIZE = 512;

    /** Window sizes for PIM (contact & calendar) sync options. */
    public static final int PIM_WINDOW_SIZE_CONTACTS = 10;
    public static final int PIM_WINDOW_SIZE_CALENDAR = 10;

    // TODO: For each type of failure, provide info about why.
    protected static final int SYNC_RESULT_DENIED = -3;
    protected static final int SYNC_RESULT_PROVISIONING_ERROR = -2;
    protected static final int SYNC_RESULT_FAILED = -1;
    protected static final int SYNC_RESULT_DONE = 0;
    protected static final int SYNC_RESULT_MORE_AVAILABLE = 1;

    protected final ContentResolver mContentResolver;
    protected final Mailbox mMailbox;
    protected final Bundle mSyncExtras;
    protected final SyncResult mSyncResult;

    protected EasSyncHandler(final Context context, final ContentResolver contentResolver,
            final Account account, final Mailbox mailbox, final Bundle syncExtras,
            final SyncResult syncResult) {
        super(context, account);
        mContentResolver = contentResolver;
        mMailbox = mailbox;
        mSyncExtras = syncExtras;
        mSyncResult = syncResult;
    }

    /**
     * Create an instance of the appropriate subclass to handle sync for mailbox.
     * @param context
     * @param contentResolver
     * @param accountManagerAccount The {@link android.accounts.Account} for this sync.
     * @param account The {@link Account} for mailbox.
     * @param mailbox The {@link Mailbox} to sync.
     * @param syncExtras The extras for this sync, for consumption by {@link #performSync}.
     * @param syncResult The output results for this sync, which may be written to by
     *      {@link #performSync}.
     * @return An appropriate EasSyncHandler for this mailbox, or null if this sync can't be
     *      handled.
     */
    public static EasSyncHandler getEasSyncHandler(final Context context,
            final ContentResolver contentResolver,
            final android.accounts.Account accountManagerAccount,
            final Account account, final Mailbox mailbox,
            final Bundle syncExtras, final SyncResult syncResult) {
        if (account != null && mailbox != null) {
            switch (mailbox.mType) {
                case Mailbox.TYPE_INBOX:
                case Mailbox.TYPE_MAIL:
                case Mailbox.TYPE_DRAFTS:
                case Mailbox.TYPE_SENT:
                case Mailbox.TYPE_TRASH:
                    return new EasMailboxSyncHandler(context, contentResolver, account, mailbox,
                            syncExtras, syncResult);
                case Mailbox.TYPE_CALENDAR:
                    return new EasCalendarSyncHandler(context, contentResolver,
                            accountManagerAccount, account, mailbox, syncExtras, syncResult);
                case Mailbox.TYPE_CONTACTS:
                    return new EasContactsSyncHandler(context, contentResolver,
                            accountManagerAccount, account, mailbox, syncExtras, syncResult);
            }
        }
        // Unknown mailbox type.
        LogUtils.e(TAG, "Invalid mailbox type %d", mailbox.mType);
        return null;
    }

    // Interface for subclasses to implement:
    // Subclasses must implement the abstract functions below to provide the information needed by
    // performSync.

    /**
     * Get the flag for traffic bookkeeping for this sync type.
     * @return The appropriate value from {@link TrafficFlags} for this sync.
     */
    protected abstract int getTrafficFlag();

    /**
     * Get the sync key for this mailbox.
     * @return The sync key for the object being synced. "0" means this is the first sync. If
     *      there is an error in getting the sync key, this function returns null.
     */
    protected String getSyncKey() {
        if (mMailbox == null) {
            return null;
        }
        if (mMailbox.mSyncKey == null) {
            mMailbox.mSyncKey = "0";
        }
        return mMailbox.mSyncKey;
    }

    /**
     * Get the folder class name for this mailbox.
     * @return The string for this folder class, as defined by the Exchange spec.
     */
    // TODO: refactor this to be the same strings as EasPingSyncHandler#handleOneMailbox.
    protected abstract String getFolderClassName();

    /**
     * Return an {@link AbstractSyncParser} appropriate for this sync type and response.
     * @param is The {@link InputStream} for the {@link EasResponse} for this sync.
     * @return The {@link AbstractSyncParser} for this response.
     * @throws IOException
     */
    protected abstract AbstractSyncParser getParser(final InputStream is) throws IOException;

    /**
     * Add to the {@link Serializer} for this sync the child elements of a Collection needed for an
     * initial sync for this collection.
     * @param s The {@link Serializer} for this sync.
     * @throws IOException
     */
    protected abstract void setInitialSyncOptions(final Serializer s) throws IOException;

    /**
     * Add to the {@link Serializer} for this sync the child elements of a Collection needed for a
     * non-initial sync for this collection, OTHER THAN Commands (which are written by
     * {@link #setUpsyncCommands}.
     *
     * @param s The {@link com.android.exchange.adapter.Serializer} for this sync.
     * @param numWindows
     * @throws IOException
     */
    protected abstract void setNonInitialSyncOptions(final Serializer s, int numWindows)
            throws IOException;

    /**
     * Add all Commands to the {@link Serializer} for this Sync request. Strictly speaking, it's
     * not all Upsync requests since Fetch is also a command, but largely that's what this section
     * is used for.
     * @param s The {@link Serializer} for this sync.
     * @throws IOException
     */
    protected abstract void setUpsyncCommands(final Serializer s) throws IOException;

    /**
     * Perform any necessary cleanup after processing a Sync response.
     */
    protected abstract void cleanup(final int syncResult);

    // End of abstract functions.

    /**
     * Shared non-initial sync options for PIM (contacts & calendar) objects.
     *
     * @param s The {@link com.android.exchange.adapter.Serializer} for this sync request.
     * @param filter The lookback to use, or null if no lookback is desired.
     * @param windowSize
     * @throws IOException
     */
    protected void setPimSyncOptions(final Serializer s, final String filter, int windowSize)
            throws IOException {
        s.tag(Tags.SYNC_DELETES_AS_MOVES);
        s.tag(Tags.SYNC_GET_CHANGES);
        s.data(Tags.SYNC_WINDOW_SIZE, String.valueOf(windowSize));
        s.start(Tags.SYNC_OPTIONS);
        // Set the filter (lookback), if provided
        if (filter != null) {
            s.data(Tags.SYNC_FILTER_TYPE, filter);
        }
        // Set the truncation amount and body type
        if (getProtocolVersion() >= Eas.SUPPORTED_PROTOCOL_EX2007_DOUBLE) {
            s.start(Tags.BASE_BODY_PREFERENCE);
            // Plain text
            s.data(Tags.BASE_TYPE, Eas.BODY_PREFERENCE_TEXT);
            s.data(Tags.BASE_TRUNCATION_SIZE, Eas.EAS12_TRUNCATION_SIZE);
            s.end();
        } else {
            s.data(Tags.SYNC_TRUNCATION, Eas.EAS2_5_TRUNCATION_SIZE);
        }
        s.end();
    }

    /**
     * Create and populate the {@link Serializer} for this Sync POST to the Exchange server.
     *
     * @param syncKey The sync key to use for this request.
     * @param initialSync Whether this sync is the first for this object.
     * @param numWindows
     * @return The {@link Serializer} for to use for this request.
     * @throws IOException
     */
    private Serializer buildEasRequest(
            final String syncKey, final boolean initialSync, int numWindows) throws IOException {
        final String className = getFolderClassName();
        LogUtils.d(TAG, "Syncing account %d mailbox %d (class %s) with syncKey %s", mAccount.mId,
                mMailbox.mId, className, syncKey);

        final Serializer s = new Serializer();

        s.start(Tags.SYNC_SYNC);
        s.start(Tags.SYNC_COLLECTIONS);
        s.start(Tags.SYNC_COLLECTION);
        // The "Class" element is removed in EAS 12.1 and later versions
        if (getProtocolVersion() < Eas.SUPPORTED_PROTOCOL_EX2007_SP1_DOUBLE) {
            s.data(Tags.SYNC_CLASS, className);
        }
        s.data(Tags.SYNC_SYNC_KEY, syncKey);
        s.data(Tags.SYNC_COLLECTION_ID, mMailbox.mServerId);
        if (initialSync) {
            setInitialSyncOptions(s);
        } else {
            setNonInitialSyncOptions(s, numWindows);
            setUpsyncCommands(s);
        }
        s.end().end().end().done();

        return s;
    }

    /**
     * Interpret a successful (HTTP code = 200) response from the Exchange server.
     * @param resp The {@link EasResponse} for the Sync message.
     * @return One of {@link #SYNC_RESULT_FAILED}, {@link #SYNC_RESULT_MORE_AVAILABLE}, or
     *      {@link #SYNC_RESULT_DONE} as appropriate for the server response.
     */
    private int parse(final EasResponse resp) {
        try {
            final AbstractSyncParser parser = getParser(resp.getInputStream());
            final boolean moreAvailable = parser.parse();
            if (moreAvailable) {
                return SYNC_RESULT_MORE_AVAILABLE;
            }
        } catch (final Parser.EmptyStreamException e) {
            // This indicates a compressed response which was empty, which is OK.
        } catch (final IOException e) {
            return SYNC_RESULT_FAILED;
        } catch (final CommandStatusException e) {
            // TODO: This is basically copied from EasOperation, will go away when this merges.
            final int status = e.mStatus;
            LogUtils.e(TAG, "CommandStatusException: %d", status);
            if (CommandStatusException.CommandStatus.isNeedsProvisioning(status)) {
               return SYNC_RESULT_PROVISIONING_ERROR;
            }
            if (CommandStatusException.CommandStatus.isDeniedAccess(status)) {
                return SYNC_RESULT_DENIED;
            }
            return SYNC_RESULT_FAILED;
        }
        return SYNC_RESULT_DONE;
    }

    /**
     * Send one Sync POST to the Exchange server, and handle the response.
     * @return One of {@link #SYNC_RESULT_FAILED}, {@link #SYNC_RESULT_MORE_AVAILABLE}, or
     *      {@link #SYNC_RESULT_DONE} as appropriate for the server response.
     * @param syncResult
     * @param numWindows
     */
    private int performOneSync(SyncResult syncResult, int numWindows) {
        final String syncKey = getSyncKey();
        if (syncKey == null) {
            return SYNC_RESULT_FAILED;
        }
        final boolean initialSync = syncKey.equals("0");

        final EasResponse resp;
        try {
            final Serializer s = buildEasRequest(syncKey, initialSync, numWindows);
            final long timeout = initialSync ? 120 * DateUtils.SECOND_IN_MILLIS : COMMAND_TIMEOUT;
            resp = sendHttpClientPost("Sync", s.toByteArray(), timeout);
        } catch (final IOException e) {
            LogUtils.e(TAG, e, "Sync error:");
            syncResult.stats.numIoExceptions++;
            return SYNC_RESULT_FAILED;
        } catch (final CertificateException e) {
            LogUtils.e(TAG, e, "Certificate error:");
            syncResult.stats.numAuthExceptions++;
            return SYNC_RESULT_FAILED;
        }

        final int result;
        try {
            final int responseResult;
            final int code = resp.getStatus();
            if (code == HttpStatus.SC_OK) {
                // A successful sync can have an empty response -- this indicates no change.
                // In the case of a compressed stream, resp will be non-empty, but parse() handles
                // that case.
                if (!resp.isEmpty()) {
                    responseResult = parse(resp);
                } else {
                    responseResult = SYNC_RESULT_DONE;
                }
            } else {
                LogUtils.e(TAG, "Sync failed with Status: " + code);
                responseResult = SYNC_RESULT_FAILED;
            }

            if (responseResult == SYNC_RESULT_DONE
                    || responseResult == SYNC_RESULT_MORE_AVAILABLE) {
                result = responseResult;
            } else if (resp.isProvisionError()
                    || responseResult == SYNC_RESULT_PROVISIONING_ERROR) {
                final EasProvision provision = new EasProvision(mContext, mAccount, this);
                if (provision.provision(syncResult, mAccount.mId)) {
                    // We handled the provisioning error, so loop.
                    LogUtils.d(TAG, "Provisioning error handled during sync, retrying");
                    result = SYNC_RESULT_MORE_AVAILABLE;
                } else {
                    syncResult.stats.numAuthExceptions++;
                    result = SYNC_RESULT_FAILED;
                }
            } else if (resp.isAuthError() || responseResult == SYNC_RESULT_DENIED) {
                syncResult.stats.numAuthExceptions++;
                result = SYNC_RESULT_FAILED;
            } else {
                syncResult.stats.numParseExceptions++;
                result = SYNC_RESULT_FAILED;
            }

        } finally {
            resp.close();
        }

        cleanup(result);

        if (initialSync && result != SYNC_RESULT_FAILED) {
            // TODO: Handle Automatic Lookback
        }

        return result;
    }

    /**
     * Perform the sync, updating {@link #mSyncResult} as appropriate (which was passed in from
     * the system SyncManager and will be read by it on the way out).
     * This function can send multiple Sync messages to the Exchange server, due to the server
     * replying to a Sync request with MoreAvailable.
     * In the case of errors, this function should not attempt any retries, but rather should
     * set {@link #mSyncResult} to reflect the problem and let the system SyncManager handle
     * any it.
     * @param syncResult
     */
    public final boolean performSync(SyncResult syncResult) {
        // Set up traffic stats bookkeeping.
        final int trafficFlags = TrafficFlags.getSyncFlags(mContext, mAccount);
        TrafficStats.setThreadStatsTag(trafficFlags | getTrafficFlag());

        // TODO: Properly handle UI status updates.
        //syncMailboxStatus(EmailServiceStatus.IN_PROGRESS, 0);
        int result = SYNC_RESULT_MORE_AVAILABLE;
        int numWindows = 1;
        String key = getSyncKey();
        while (result == SYNC_RESULT_MORE_AVAILABLE) {
            result = performOneSync(syncResult, numWindows);
            // TODO: Clear pending request queue.
            final String newKey = getSyncKey();
            if (result == SYNC_RESULT_MORE_AVAILABLE && key.equals(newKey)) {
                LogUtils.e(TAG,
                        "Server has more data but we have the same key: %s numWindows: %d",
                        key, numWindows);
                numWindows++;
            } else {
                numWindows = 1;
            }
            key = newKey;
        }
        return result == SYNC_RESULT_DONE;
    }
}
