/*
 * Copyright (C) 2009 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.contacts.common.model;

import android.content.ContentProviderOperation;
import android.content.ContentProviderOperation.Builder;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Entity;
import android.content.EntityIterator;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.provider.ContactsContract.AggregationExceptions;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.RawContacts;
import android.util.Log;

import com.android.contacts.common.compat.CompatUtils;

import com.google.common.collect.Lists;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;

/**
 * Container for multiple {@link RawContactDelta} objects, usually when editing
 * together as an entire aggregate. Provides convenience methods for parceling
 * and applying another {@link RawContactDeltaList} over it.
 */
public class RawContactDeltaList extends ArrayList<RawContactDelta> implements Parcelable {
    private static final String TAG = RawContactDeltaList.class.getSimpleName();
    private static final boolean VERBOSE_LOGGING = Log.isLoggable(TAG, Log.VERBOSE);

    private boolean mSplitRawContacts;
    private long[] mJoinWithRawContactIds;

    public RawContactDeltaList() {
    }

    /**
     * Create an {@link RawContactDeltaList} based on {@link Contacts} specified by the
     * given query parameters. This closes the {@link EntityIterator} when
     * finished, so it doesn't subscribe to updates.
     */
    public static RawContactDeltaList fromQuery(Uri entityUri, ContentResolver resolver,
            String selection, String[] selectionArgs, String sortOrder) {
        final EntityIterator iterator = RawContacts.newEntityIterator(
                resolver.query(entityUri, null, selection, selectionArgs, sortOrder));
        try {
            return fromIterator(iterator);
        } finally {
            iterator.close();
        }
    }

    /**
     * Create an {@link RawContactDeltaList} that contains the entities of the Iterator as before
     * values.  This function can be passed an iterator of Entity objects or an iterator of
     * RawContact objects.
     */
    public static RawContactDeltaList fromIterator(Iterator<?> iterator) {
        final RawContactDeltaList state = new RawContactDeltaList();
        state.addAll(iterator);
        return state;
    }

    public void addAll(Iterator<?> iterator) {
        // Perform background query to pull contact details
        while (iterator.hasNext()) {
            // Read all contacts into local deltas to prepare for edits
            Object nextObject = iterator.next();
            final RawContact before = nextObject instanceof Entity
                    ? RawContact.createFrom((Entity) nextObject)
                    : (RawContact) nextObject;
            final RawContactDelta rawContactDelta = RawContactDelta.fromBefore(before);
            add(rawContactDelta);
        }
    }

    /**
     * Merge the "after" values from the given {@link RawContactDeltaList}, discarding any
     * previous "after" states. This is typically used when re-parenting user
     * edits onto an updated {@link RawContactDeltaList}.
     */
    public static RawContactDeltaList mergeAfter(RawContactDeltaList local,
            RawContactDeltaList remote) {
        if (local == null) local = new RawContactDeltaList();

        // For each entity in the remote set, try matching over existing
        for (RawContactDelta remoteEntity : remote) {
            final Long rawContactId = remoteEntity.getValues().getId();

            // Find or create local match and merge
            final RawContactDelta localEntity = local.getByRawContactId(rawContactId);
            final RawContactDelta merged = RawContactDelta.mergeAfter(localEntity, remoteEntity);

            if (localEntity == null && merged != null) {
                // No local entry before, so insert
                local.add(merged);
            }
        }

        return local;
    }

    /**
     * Build a list of {@link ContentProviderOperation} that will transform all
     * the "before" {@link Entity} states into the modified state which all
     * {@link RawContactDelta} objects represent. This method specifically creates
     * any {@link AggregationExceptions} rules needed to groups edits together.
     */
    public ArrayList<ContentProviderOperation> buildDiff() {
        if (VERBOSE_LOGGING) {
            Log.v(TAG, "buildDiff: list=" + toString());
        }
        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();

        final long rawContactId = this.findRawContactId();
        int firstInsertRow = -1;

        // First pass enforces versions remain consistent
        for (RawContactDelta delta : this) {
            delta.buildAssert(diff);
        }

        final int assertMark = diff.size();
        int backRefs[] = new int[size()];

        int rawContactIndex = 0;

        // Second pass builds actual operations
        for (RawContactDelta delta : this) {
            final int firstBatch = diff.size();
            final boolean isInsert = delta.isContactInsert();
            backRefs[rawContactIndex++] = isInsert ? firstBatch : -1;

            delta.buildDiff(diff);

            // If the user chose to join with some other existing raw contact(s) at save time,
            // add aggregation exceptions for all those raw contacts.
            if (mJoinWithRawContactIds != null) {
                for (Long joinedRawContactId : mJoinWithRawContactIds) {
                    final Builder builder = beginKeepTogether();
                    builder.withValue(AggregationExceptions.RAW_CONTACT_ID1, joinedRawContactId);
                    if (rawContactId != -1) {
                        builder.withValue(AggregationExceptions.RAW_CONTACT_ID2, rawContactId);
                    } else {
                        builder.withValueBackReference(
                                AggregationExceptions.RAW_CONTACT_ID2, firstBatch);
                    }
                    diff.add(builder.build());
                }
            }

            // Only create rules for inserts
            if (!isInsert) continue;

            // If we are going to split all contacts, there is no point in first combining them
            if (mSplitRawContacts) continue;

            if (rawContactId != -1) {
                // Has existing contact, so bind to it strongly
                final Builder builder = beginKeepTogether();
                builder.withValue(AggregationExceptions.RAW_CONTACT_ID1, rawContactId);
                builder.withValueBackReference(AggregationExceptions.RAW_CONTACT_ID2, firstBatch);
                diff.add(builder.build());

            } else if (firstInsertRow == -1) {
                // First insert case, so record row
                firstInsertRow = firstBatch;

            } else {
                // Additional insert case, so point at first insert
                final Builder builder = beginKeepTogether();
                builder.withValueBackReference(AggregationExceptions.RAW_CONTACT_ID1,
                        firstInsertRow);
                builder.withValueBackReference(AggregationExceptions.RAW_CONTACT_ID2, firstBatch);
                diff.add(builder.build());
            }
        }

        if (mSplitRawContacts) {
            buildSplitContactDiff(diff, backRefs);
        }

        // No real changes if only left with asserts
        if (diff.size() == assertMark) {
            diff.clear();
        }
        if (VERBOSE_LOGGING) {
            Log.v(TAG, "buildDiff: ops=" + diffToString(diff));
        }
        return diff;
    }

    /**
     * For compatibility purpose, this method is copied from {@link #buildDiff} and returns an
     * ArrayList of CPOWrapper.
     */
    public ArrayList<CPOWrapper> buildDiffWrapper() {
        if (VERBOSE_LOGGING) {
            Log.v(TAG, "buildDiffWrapper: list=" + toString());
        }
        final ArrayList<CPOWrapper> diffWrapper = Lists.newArrayList();

        final long rawContactId = this.findRawContactId();
        int firstInsertRow = -1;

        // First pass enforces versions remain consistent
        for (RawContactDelta delta : this) {
            delta.buildAssertWrapper(diffWrapper);
        }

        final int assertMark = diffWrapper.size();
        int backRefs[] = new int[size()];

        int rawContactIndex = 0;

        // Second pass builds actual operations
        for (RawContactDelta delta : this) {
            final int firstBatch = diffWrapper.size();
            final boolean isInsert = delta.isContactInsert();
            backRefs[rawContactIndex++] = isInsert ? firstBatch : -1;

            delta.buildDiffWrapper(diffWrapper);

            // If the user chose to join with some other existing raw contact(s) at save time,
            // add aggregation exceptions for all those raw contacts.
            if (mJoinWithRawContactIds != null) {
                for (Long joinedRawContactId : mJoinWithRawContactIds) {
                    final Builder builder = beginKeepTogether();
                    builder.withValue(AggregationExceptions.RAW_CONTACT_ID1, joinedRawContactId);
                    if (rawContactId != -1) {
                        builder.withValue(AggregationExceptions.RAW_CONTACT_ID2, rawContactId);
                    } else {
                        builder.withValueBackReference(
                                AggregationExceptions.RAW_CONTACT_ID2, firstBatch);
                    }
                    diffWrapper.add(new CPOWrapper(builder.build(), CompatUtils.TYPE_UPDATE));
                }
            }

            // Only create rules for inserts
            if (!isInsert) continue;

            // If we are going to split all contacts, there is no point in first combining them
            if (mSplitRawContacts) continue;

            if (rawContactId != -1) {
                // Has existing contact, so bind to it strongly
                final Builder builder = beginKeepTogether();
                builder.withValue(AggregationExceptions.RAW_CONTACT_ID1, rawContactId);
                builder.withValueBackReference(AggregationExceptions.RAW_CONTACT_ID2, firstBatch);
                diffWrapper.add(new CPOWrapper(builder.build(), CompatUtils.TYPE_UPDATE));

            } else if (firstInsertRow == -1) {
                // First insert case, so record row
                firstInsertRow = firstBatch;

            } else {
                // Additional insert case, so point at first insert
                final Builder builder = beginKeepTogether();
                builder.withValueBackReference(AggregationExceptions.RAW_CONTACT_ID1,
                        firstInsertRow);
                builder.withValueBackReference(AggregationExceptions.RAW_CONTACT_ID2, firstBatch);
                diffWrapper.add(new CPOWrapper(builder.build(), CompatUtils.TYPE_UPDATE));
            }
        }

        if (mSplitRawContacts) {
            buildSplitContactDiffWrapper(diffWrapper, backRefs);
        }

        // No real changes if only left with asserts
        if (diffWrapper.size() == assertMark) {
            diffWrapper.clear();
        }
        if (VERBOSE_LOGGING) {
            Log.v(TAG, "buildDiff: ops=" + diffToStringWrapper(diffWrapper));
        }
        return diffWrapper;
    }

    private static String diffToString(ArrayList<ContentProviderOperation> ops) {
        final StringBuilder sb = new StringBuilder();
        sb.append("[\n");
        for (ContentProviderOperation op : ops) {
            sb.append(op.toString());
            sb.append(",\n");
        }
        sb.append("]\n");
        return sb.toString();
    }

    /**
     * For compatibility purpose.
     */
    private static String diffToStringWrapper(ArrayList<CPOWrapper> cpoWrappers) {
        ArrayList<ContentProviderOperation> ops = Lists.newArrayList();
        for (CPOWrapper cpoWrapper : cpoWrappers) {
            ops.add(cpoWrapper.getOperation());
        }
        return diffToString(ops);
    }

    /**
     * Start building a {@link ContentProviderOperation} that will keep two
     * {@link RawContacts} together.
     */
    protected Builder beginKeepTogether() {
        final Builder builder = ContentProviderOperation
                .newUpdate(AggregationExceptions.CONTENT_URI);
        builder.withValue(AggregationExceptions.TYPE, AggregationExceptions.TYPE_KEEP_TOGETHER);
        return builder;
    }

    /**
     * Builds {@link AggregationExceptions} to split all constituent raw contacts into
     * separate contacts.
     */
    private void buildSplitContactDiff(final ArrayList<ContentProviderOperation> diff,
            int[] backRefs) {
        final int count = size();
        for (int i = 0; i < count; i++) {
            for (int j = 0; j < count; j++) {
                if (i == j) {
                    continue;
                }
                final Builder builder = buildSplitContactDiffHelper(i, j, backRefs);
                if (builder != null) {
                    diff.add(builder.build());
                }
            }
        }
    }

    /**
     * For compatibility purpose, this method is copied from {@link #buildSplitContactDiff} and
     * takes an ArrayList of CPOWrapper as parameter.
     */
    private void buildSplitContactDiffWrapper(final ArrayList<CPOWrapper> diff, int[] backRefs) {
        final int count = size();
        for (int i = 0; i < count; i++) {
            for (int j = 0; j < count; j++) {
                if (i == j) {
                    continue;
                }
                final Builder builder = buildSplitContactDiffHelper(i, j, backRefs);
                if (builder != null) {
                    diff.add(new CPOWrapper(builder.build(), CompatUtils.TYPE_UPDATE));
                }
            }
        }
    }

    private Builder buildSplitContactDiffHelper(int index1, int index2, int[] backRefs) {
        final Builder builder =
                ContentProviderOperation.newUpdate(AggregationExceptions.CONTENT_URI);
        builder.withValue(AggregationExceptions.TYPE, AggregationExceptions.TYPE_KEEP_SEPARATE);

        Long rawContactId1 = get(index1).getValues().getAsLong(RawContacts._ID);
        int backRef1 = backRefs[index1];
        if (rawContactId1 != null && rawContactId1 >= 0) {
            builder.withValue(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1);
        } else if (backRef1 >= 0) {
            builder.withValueBackReference(AggregationExceptions.RAW_CONTACT_ID1, backRef1);
        } else {
            return null;
        }

        Long rawContactId2 = get(index2).getValues().getAsLong(RawContacts._ID);
        int backRef2 = backRefs[index2];
        if (rawContactId2 != null && rawContactId2 >= 0) {
            builder.withValue(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2);
        } else if (backRef2 >= 0) {
            builder.withValueBackReference(AggregationExceptions.RAW_CONTACT_ID2, backRef2);
        } else {
            return null;
        }
        return builder;
    }

    /**
     * Search all contained {@link RawContactDelta} for the first one with an
     * existing {@link RawContacts#_ID} value. Usually used when creating
     * {@link AggregationExceptions} during an update.
     */
    public long findRawContactId() {
        for (RawContactDelta delta : this) {
            final Long rawContactId = delta.getValues().getAsLong(RawContacts._ID);
            if (rawContactId != null && rawContactId >= 0) {
                return rawContactId;
            }
        }
        return -1;
    }

    /**
     * Find {@link RawContacts#_ID} of the requested {@link RawContactDelta}.
     */
    public Long getRawContactId(int index) {
        if (index >= 0 && index < this.size()) {
            final RawContactDelta delta = this.get(index);
            final ValuesDelta values = delta.getValues();
            if (values.isVisible()) {
                return values.getAsLong(RawContacts._ID);
            }
        }
        return null;
    }

    /**
     * Find the raw-contact (an {@link RawContactDelta}) with the specified ID.
     */
    public RawContactDelta getByRawContactId(Long rawContactId) {
        final int index = this.indexOfRawContactId(rawContactId);
        return (index == -1) ? null : this.get(index);
    }

    /**
     * Find index of given {@link RawContacts#_ID} when present.
     */
    public int indexOfRawContactId(Long rawContactId) {
        if (rawContactId == null) return -1;
        final int size = this.size();
        for (int i = 0; i < size; i++) {
            final Long currentId = getRawContactId(i);
            if (rawContactId.equals(currentId)) {
                return i;
            }
        }
        return -1;
    }

    /**
     * Return the index of the first RawContactDelta corresponding to a writable raw-contact, or -1.
     * */
    public int indexOfFirstWritableRawContact(Context context) {
        // Find the first writable entity.
        int entityIndex = 0;
        for (RawContactDelta delta : this) {
            if (delta.getRawContactAccountType(context).areContactsWritable()) return entityIndex;
            entityIndex++;
        }
        return -1;
    }

    /**  Return the first RawContactDelta corresponding to a writable raw-contact, or null. */
    public RawContactDelta getFirstWritableRawContact(Context context) {
        final int index = indexOfFirstWritableRawContact(context);
        return (index == -1) ? null : get(index);
    }

    public ValuesDelta getSuperPrimaryEntry(final String mimeType) {
        ValuesDelta primary = null;
        ValuesDelta randomEntry = null;
        for (RawContactDelta delta : this) {
            final ArrayList<ValuesDelta> mimeEntries = delta.getMimeEntries(mimeType);
            if (mimeEntries == null) return null;

            for (ValuesDelta entry : mimeEntries) {
                if (entry.isSuperPrimary()) {
                    return entry;
                } else if (primary == null && entry.isPrimary()) {
                    primary = entry;
                } else if (randomEntry == null) {
                    randomEntry = entry;
                }
            }
        }
        // When no direct super primary, return something
        if (primary != null) {
            return primary;
        }
        return randomEntry;
    }

    /**
     * Sets a flag that will split ("explode") the raw_contacts into seperate contacts
     */
    public void markRawContactsForSplitting() {
        mSplitRawContacts = true;
    }

    public boolean isMarkedForSplitting() {
        return mSplitRawContacts;
    }

    public void setJoinWithRawContacts(long[] rawContactIds) {
        mJoinWithRawContactIds = rawContactIds;
    }

    public boolean isMarkedForJoining() {
        return mJoinWithRawContactIds != null && mJoinWithRawContactIds.length > 0;
    }

    /** {@inheritDoc} */
    @Override
    public int describeContents() {
        // Nothing special about this parcel
        return 0;
    }

    /** {@inheritDoc} */
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        final int size = this.size();
        dest.writeInt(size);
        for (RawContactDelta delta : this) {
            dest.writeParcelable(delta, flags);
        }
        dest.writeLongArray(mJoinWithRawContactIds);
        dest.writeInt(mSplitRawContacts ? 1 : 0);
    }

    @SuppressWarnings("unchecked")
    public void readFromParcel(Parcel source) {
        final ClassLoader loader = getClass().getClassLoader();
        final int size = source.readInt();
        for (int i = 0; i < size; i++) {
            this.add(source.<RawContactDelta> readParcelable(loader));
        }
        mJoinWithRawContactIds = source.createLongArray();
        mSplitRawContacts = source.readInt() != 0;
    }

    public static final Parcelable.Creator<RawContactDeltaList> CREATOR =
            new Parcelable.Creator<RawContactDeltaList>() {
        @Override
        public RawContactDeltaList createFromParcel(Parcel in) {
            final RawContactDeltaList state = new RawContactDeltaList();
            state.readFromParcel(in);
            return state;
        }

        @Override
        public RawContactDeltaList[] newArray(int size) {
            return new RawContactDeltaList[size];
        }
    };

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("(");
        sb.append("Split=");
        sb.append(mSplitRawContacts);
        sb.append(", Join=[");
        sb.append(Arrays.toString(mJoinWithRawContactIds));
        sb.append("], Values=");
        sb.append(super.toString());
        sb.append(")");
        return sb.toString();
    }
}
