/*
 * Copyright (C) 2008-2009 Marc Blank
 * Licensed to 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.adapter;

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.EasSyncService;
import com.google.common.annotations.VisibleForTesting;

import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.OperationApplicationException;
import android.net.Uri;
import android.os.RemoteException;
import android.os.TransactionTooLargeException;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

/**
 * Parent class of all sync adapters (EasMailbox, EasCalendar, and EasContacts)
 *
 */
public abstract class AbstractSyncAdapter {

    public static final int SECONDS = 1000;
    public static final int MINUTES = SECONDS*60;
    public static final int HOURS = MINUTES*60;
    public static final int DAYS = HOURS*24;
    public static final int WEEKS = DAYS*7;

    protected static final String PIM_WINDOW_SIZE = "4";

    private static final long SEPARATOR_ID = Long.MAX_VALUE;

    public Mailbox mMailbox;
    public EasSyncService mService;
    public Context mContext;
    public Account mAccount;
    public final ContentResolver mContentResolver;
    public final android.accounts.Account mAccountManagerAccount;

    // Create the data for local changes that need to be sent up to the server
    public abstract boolean sendLocalChanges(Serializer s) throws IOException;
    // Parse incoming data from the EAS server, creating, modifying, and deleting objects as
    // required through the EmailProvider
    public abstract boolean parse(InputStream is) throws IOException, CommandStatusException;
    // The name used to specify the collection type of the target (Email, Calendar, or Contacts)
    public abstract String getCollectionName();
    public abstract void cleanup();
    public abstract boolean isSyncable();
    // Add sync options (filter, body type - html vs plain, and truncation)
    public abstract void sendSyncOptions(Double protocolVersion, Serializer s) throws IOException;
    /**
     * Delete all records of this class in this account
     */
    public abstract void wipe();

    public boolean isLooping() {
        return false;
    }

    public AbstractSyncAdapter(EasSyncService service) {
        mService = service;
        mMailbox = service.mMailbox;
        mContext = service.mContext;
        mAccount = service.mAccount;
        mAccountManagerAccount = new android.accounts.Account(mAccount.mEmailAddress,
                Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE);
        mContentResolver = mContext.getContentResolver();
    }

    public void userLog(String ...strings) {
        mService.userLog(strings);
    }

    public void incrementChangeCount() {
        mService.mChangeCount++;
    }

    /**
     * Set sync options common to PIM's (contacts and calendar)
     * @param protocolVersion the protocol version under which we're syncing
     * @param the filter to use (or null)
     * @param s the Serializer
     * @throws IOException
     */
    protected void setPimSyncOptions(Double protocolVersion, String filter, Serializer s)
            throws IOException {
        s.tag(Tags.SYNC_DELETES_AS_MOVES);
        s.tag(Tags.SYNC_GET_CHANGES);
        s.data(Tags.SYNC_WINDOW_SIZE, PIM_WINDOW_SIZE);
        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 (protocolVersion >= 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();
    }

    /**
     * Returns the current SyncKey; override if the SyncKey is stored elsewhere (as for Contacts)
     * @return the current SyncKey for the Mailbox
     * @throws IOException
     */
    public String getSyncKey() throws IOException {
        if (mMailbox.mSyncKey == null) {
            userLog("Reset SyncKey to 0");
            mMailbox.mSyncKey = "0";
        }
        return mMailbox.mSyncKey;
    }

    public void setSyncKey(String syncKey, boolean inCommands) throws IOException {
        mMailbox.mSyncKey = syncKey;
    }

    /**
     * Operation is our binder-safe ContentProviderOperation (CPO) construct; an Operation can
     * be created from a CPO, a CPO Builder, or a CPO Builder with a "back reference" column name
     * and offset (that might be used in Builder.withValueBackReference).  The CPO is not actually
     * built until it is ready to be executed (with applyBatch); this allows us to recalculate
     * back reference offsets if we are required to re-send a large batch in smaller chunks.
     *
     * NOTE: A failed binder transaction is something of an emergency case, and shouldn't happen
     * with any frequency.  When it does, and we are forced to re-send the data to the content
     * provider in smaller chunks, we DO lose the sync-window atomicity, and thereby add another
     * small risk to the data.  Of course, this is far, far better than dropping the data on the
     * floor, as was done before the framework implemented TransactionTooLargeException
     */
    protected static class Operation {
        final ContentProviderOperation mOp;
        final ContentProviderOperation.Builder mBuilder;
        final String mColumnName;
        final int mOffset;
        // Is this Operation a separator? (a good place to break up a large transaction)
        boolean mSeparator = false;

        // For toString()
        final String[] TYPES = new String[] {"???", "Ins", "Upd", "Del", "Assert"};

        Operation(ContentProviderOperation.Builder builder, String columnName, int offset) {
            mOp = null;
            mBuilder = builder;
            mColumnName = columnName;
            mOffset = offset;
        }

        Operation(ContentProviderOperation.Builder builder) {
            mOp = null;
            mBuilder = builder;
            mColumnName = null;
            mOffset = 0;
        }

        Operation(ContentProviderOperation op) {
            mOp = op;
            mBuilder = null;
            mColumnName = null;
            mOffset = 0;
        }

        public String toString() {
            StringBuilder sb = new StringBuilder("Op: ");
            ContentProviderOperation op = operationToContentProviderOperation(this, 0);
            int type = 0;
            //DO NOT SHIP WITH THE FOLLOWING LINE (the API is hidden!)
            //type = op.getType();
            sb.append(TYPES[type]);
            Uri uri = op.getUri();
            sb.append(' ');
            sb.append(uri.getPath());
            if (mColumnName != null) {
                sb.append(" Back value of " + mColumnName + ": " + mOffset);
            }
            return sb.toString();
        }
    }

    /**
     * We apply the batch of CPO's here.  We synchronize on the service to avoid thread-nasties,
     * and we just return quickly if the service has already been stopped.
     */
    private ContentProviderResult[] execute(String authority,
            ArrayList<ContentProviderOperation> ops)
            throws RemoteException, OperationApplicationException {
        synchronized (mService.getSynchronizer()) {
            if (!mService.isStopped()) {
                if (!ops.isEmpty()) {
                    ContentProviderResult[] result = mContentResolver.applyBatch(authority, ops);
                    mService.userLog("Results: " + result.length);
                    return result;
                }
            }
        }
        return new ContentProviderResult[0];
    }

    /**
     * Convert an Operation to a CPO; if the Operation has a back reference, apply it with the
     * passed-in offset
     */
    @VisibleForTesting
    static ContentProviderOperation operationToContentProviderOperation(Operation op, int offset) {
        if (op.mOp != null) {
            return op.mOp;
        } else if (op.mBuilder == null) {
            throw new IllegalArgumentException("Operation must have CPO.Builder");
        }
        ContentProviderOperation.Builder builder = op.mBuilder;
        if (op.mColumnName != null) {
            builder.withValueBackReference(op.mColumnName, op.mOffset - offset);
        }
        return builder.build();
    }

    /**
     * Create a list of CPOs from a list of Operations, and then apply them in a batch
     */
    private ContentProviderResult[] applyBatch(String authority, ArrayList<Operation> ops,
            int offset) throws RemoteException, OperationApplicationException {
        // Handle the empty case
        if (ops.isEmpty()) {
            return new ContentProviderResult[0];
        }
        ArrayList<ContentProviderOperation> cpos = new ArrayList<ContentProviderOperation>();
        for (Operation op: ops) {
            cpos.add(operationToContentProviderOperation(op, offset));
        }
        return execute(authority, cpos);
    }

    /**
     * Apply the list of CPO's in the provider and copy the "mini" result into our full result array
     */
    private void applyAndCopyResults(String authority, ArrayList<Operation> mini,
            ContentProviderResult[] result, int offset) throws RemoteException {
        // Empty lists are ok; we just ignore them
        if (mini.isEmpty()) return;
        try {
            ContentProviderResult[] miniResult = applyBatch(authority, mini, offset);
            // Copy the results from this mini-batch into our results array
            System.arraycopy(miniResult, 0, result, offset, miniResult.length);
        } catch (OperationApplicationException e) {
            // Not possible since we're building the ops ourselves
        }
    }

    /**
     * Called by a sync adapter to execute a list of Operations in the ContentProvider handling
     * the passed-in authority.  If the attempt to apply the batch fails due to a too-large
     * binder transaction, we split the Operations as directed by separators.  If any of the
     * "mini" batches fails due to a too-large transaction, we're screwed, but this would be
     * vanishingly rare.  Other, possibly transient, errors are handled by throwing a
     * RemoteException, which the caller will likely re-throw as an IOException so that the sync
     * can be attempted again.
     *
     * Callers MAY leave a dangling separator at the end of the list; note that the separators
     * themselves are only markers and are not sent to the provider.
     */
    protected ContentProviderResult[] safeExecute(String authority, ArrayList<Operation> ops)
            throws RemoteException {
        mService.userLog("Try to execute ", ops.size(), " CPO's for " + authority);
        ContentProviderResult[] result = null;
        try {
            // Try to execute the whole thing
            return applyBatch(authority, ops, 0);
        } catch (TransactionTooLargeException e) {
            // Nope; split into smaller chunks, demarcated by the separator operation
            mService.userLog("Transaction too large; spliting!");
            ArrayList<Operation> mini = new ArrayList<Operation>();
            // Build a result array with the total size we're sending
            result = new ContentProviderResult[ops.size()];
            int count = 0;
            int offset = 0;
            for (Operation op: ops) {
                if (op.mSeparator) {
                    try {
                        mService.userLog("Try mini-batch of ", mini.size(), " CPO's");
                        applyAndCopyResults(authority, mini, result, offset);
                        mini.clear();
                        // Save away the offset here; this will need to be subtracted out of the
                        // value originally set by the adapter
                        offset = count + 1; // Remember to add 1 for the separator!
                    } catch (TransactionTooLargeException e1) {
                        throw new RuntimeException("Can't send transaction; sync stopped.");
                    } catch (RemoteException e1) {
                        throw e1;
                    }
                } else {
                    mini.add(op);
                }
                count++;
            }
            // Check out what's left; if it's more than just a separator, apply the batch
            int miniSize = mini.size();
            if ((miniSize > 0) && !(miniSize == 1 && mini.get(0).mSeparator)) {
                applyAndCopyResults(authority, mini, result, offset);
            }
        } catch (RemoteException e) {
            throw e;
        } catch (OperationApplicationException e) {
            // Not possible since we're building the ops ourselves
        }
        return result;
    }

    /**
     * Called by a sync adapter to indicate a relatively safe place to split a batch of CPO's
     */
    protected void addSeparatorOperation(ArrayList<Operation> ops, Uri uri) {
        Operation op = new Operation(
                ContentProviderOperation.newDelete(ContentUris.withAppendedId(uri, SEPARATOR_ID)));
        op.mSeparator = true;
        ops.add(op);
    }
}

