/*
 * Copyright (C) 2012 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.ContentValues;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.provider.BaseColumns;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.text.TextUtils;

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

import com.google.common.collect.Sets;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * Type of {@link android.content.ContentValues} that maintains both an original state and a
 * modified version of that state. This allows us to build insert, update,
 * or delete operations based on a "before" {@link Entity} snapshot.
 */
public class ValuesDelta implements Parcelable {
    protected ContentValues mBefore;
    protected ContentValues mAfter;
    protected String mIdColumn = BaseColumns._ID;
    private boolean mFromTemplate;

    /**
     * Next value to assign to {@link #mIdColumn} when building an insert
     * operation through {@link #fromAfter(android.content.ContentValues)}. This is used so
     * we can concretely reference this {@link ValuesDelta} before it has
     * been persisted.
     */
    protected static int sNextInsertId = -1;

    protected ValuesDelta() {
    }

    /**
     * Create {@link ValuesDelta}, using the given object as the
     * "before" state, usually from an {@link Entity}.
     */
    public static ValuesDelta fromBefore(ContentValues before) {
        final ValuesDelta entry = new ValuesDelta();
        entry.mBefore = before;
        entry.mAfter = new ContentValues();
        return entry;
    }

    /**
     * Create {@link ValuesDelta}, using the given object as the "after"
     * state, usually when we are inserting a row instead of updating.
     */
    public static ValuesDelta fromAfter(ContentValues after) {
        final ValuesDelta entry = new ValuesDelta();
        entry.mBefore = null;
        entry.mAfter = after;

        // Assign temporary id which is dropped before insert.
        entry.mAfter.put(entry.mIdColumn, sNextInsertId--);
        return entry;
    }

    public ContentValues getAfter() {
        return mAfter;
    }

    public ContentValues getBefore() {
        return mBefore;
    }

    public boolean containsKey(String key) {
        return ((mAfter != null && mAfter.containsKey(key)) ||
                (mBefore != null && mBefore.containsKey(key)));
    }

    public String getAsString(String key) {
        if (mAfter != null && mAfter.containsKey(key)) {
            return mAfter.getAsString(key);
        } else if (mBefore != null && mBefore.containsKey(key)) {
            return mBefore.getAsString(key);
        } else {
            return null;
        }
    }

    public byte[] getAsByteArray(String key) {
        if (mAfter != null && mAfter.containsKey(key)) {
            return mAfter.getAsByteArray(key);
        } else if (mBefore != null && mBefore.containsKey(key)) {
            return mBefore.getAsByteArray(key);
        } else {
            return null;
        }
    }

    public Long getAsLong(String key) {
        if (mAfter != null && mAfter.containsKey(key)) {
            return mAfter.getAsLong(key);
        } else if (mBefore != null && mBefore.containsKey(key)) {
            return mBefore.getAsLong(key);
        } else {
            return null;
        }
    }

    public Integer getAsInteger(String key) {
        return getAsInteger(key, null);
    }

    public Integer getAsInteger(String key, Integer defaultValue) {
        if (mAfter != null && mAfter.containsKey(key)) {
            return mAfter.getAsInteger(key);
        } else if (mBefore != null && mBefore.containsKey(key)) {
            return mBefore.getAsInteger(key);
        } else {
            return defaultValue;
        }
    }

    public boolean isChanged(String key) {
        if (mAfter == null || !mAfter.containsKey(key)) {
            return false;
        }

        Object newValue = mAfter.get(key);
        Object oldValue = mBefore.get(key);

        if (oldValue == null) {
            return newValue != null;
        }

        return !oldValue.equals(newValue);
    }

    public String getMimetype() {
        return getAsString(ContactsContract.Data.MIMETYPE);
    }

    public Long getId() {
        return getAsLong(mIdColumn);
    }

    public void setIdColumn(String idColumn) {
        mIdColumn = idColumn;
    }

    public boolean isPrimary() {
        final Long isPrimary = getAsLong(ContactsContract.Data.IS_PRIMARY);
        return isPrimary == null ? false : isPrimary != 0;
    }

    public void setFromTemplate(boolean isFromTemplate) {
        mFromTemplate = isFromTemplate;
    }

    public boolean isFromTemplate() {
        return mFromTemplate;
    }

    public boolean isSuperPrimary() {
        final Long isSuperPrimary = getAsLong(ContactsContract.Data.IS_SUPER_PRIMARY);
        return isSuperPrimary == null ? false : isSuperPrimary != 0;
    }

    public boolean beforeExists() {
        return (mBefore != null && mBefore.containsKey(mIdColumn));
    }

    /**
     * When "after" is present, then visible
     */
    public boolean isVisible() {
        return (mAfter != null);
    }

    /**
     * When "after" is wiped, action is "delete"
     */
    public boolean isDelete() {
        return beforeExists() && (mAfter == null);
    }

    /**
     * When no "before" or "after", is transient
     */
    public boolean isTransient() {
        return (mBefore == null) && (mAfter == null);
    }

    /**
     * When "after" has some changes, action is "update"
     */
    public boolean isUpdate() {
        if (!beforeExists() || mAfter == null || mAfter.size() == 0) {
            return false;
        }
        for (String key : mAfter.keySet()) {
            Object newValue = mAfter.get(key);
            Object oldValue = mBefore.get(key);
            if (oldValue == null) {
                if (newValue != null) {
                    return true;
                }
            } else if (!oldValue.equals(newValue)) {
                return true;
            }
        }
        return false;
    }

    /**
     * When "after" has no changes, action is no-op
     */
    public boolean isNoop() {
        return beforeExists() && (mAfter != null && mAfter.size() == 0);
    }

    /**
     * When no "before" id, and has "after", action is "insert"
     */
    public boolean isInsert() {
        return !beforeExists() && (mAfter != null);
    }

    public void markDeleted() {
        mAfter = null;
    }

    /**
     * Ensure that our internal structure is ready for storing updates.
     */
    private void ensureUpdate() {
        if (mAfter == null) {
            mAfter = new ContentValues();
        }
    }

    public void put(String key, String value) {
        ensureUpdate();
        mAfter.put(key, value);
    }

    public void put(String key, byte[] value) {
        ensureUpdate();
        mAfter.put(key, value);
    }

    public void put(String key, int value) {
        ensureUpdate();
        mAfter.put(key, value);
    }

    public void put(String key, long value) {
        ensureUpdate();
        mAfter.put(key, value);
    }

    public void putNull(String key) {
        ensureUpdate();
        mAfter.putNull(key);
    }

    public void copyStringFrom(ValuesDelta from, String key) {
        ensureUpdate();
        if (containsKey(key) || from.containsKey(key)) {
            put(key, from.getAsString(key));
        }
    }

    /**
     * Return set of all keys defined through this object.
     */
    public Set<String> keySet() {
        final HashSet<String> keys = Sets.newHashSet();

        if (mBefore != null) {
            for (Map.Entry<String, Object> entry : mBefore.valueSet()) {
                keys.add(entry.getKey());
            }
        }

        if (mAfter != null) {
            for (Map.Entry<String, Object> entry : mAfter.valueSet()) {
                keys.add(entry.getKey());
            }
        }

        return keys;
    }

    /**
     * Return complete set of "before" and "after" values mixed together,
     * giving full state regardless of edits.
     */
    public ContentValues getCompleteValues() {
        final ContentValues values = new ContentValues();
        if (mBefore != null) {
            values.putAll(mBefore);
        }
        if (mAfter != null) {
            values.putAll(mAfter);
        }
        if (values.containsKey(ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID)) {
            // Clear to avoid double-definitions, and prefer rows
            values.remove(ContactsContract.CommonDataKinds.GroupMembership.GROUP_SOURCE_ID);
        }

        return values;
    }

    /**
     * Merge the "after" values from the given {@link ValuesDelta},
     * discarding any existing "after" state. This is typically used when
     * re-parenting changes onto an updated {@link Entity}.
     */
    public static ValuesDelta mergeAfter(ValuesDelta local, ValuesDelta remote) {
        // Bail early if trying to merge delete with missing local
        if (local == null && (remote.isDelete() || remote.isTransient())) return null;

        // Create local version if none exists yet
        if (local == null) local = new ValuesDelta();

        if (!local.beforeExists()) {
            // Any "before" record is missing, so take all values as "insert"
            local.mAfter = remote.getCompleteValues();
        } else {
            // Existing "update" with only "after" values
            local.mAfter = remote.mAfter;
        }

        return local;
    }

    @Override
    public boolean equals(Object object) {
        if (object instanceof ValuesDelta) {
            // Only exactly equal with both are identical subsets
            final ValuesDelta other = (ValuesDelta)object;
            return this.subsetEquals(other) && other.subsetEquals(this);
        }
        return false;
    }

    @Override
    public String toString() {
        final StringBuilder builder = new StringBuilder();
        toString(builder);
        return builder.toString();
    }

    /**
     * Helper for building string representation, leveraging the given
     * {@link StringBuilder} to minimize allocations.
     */
    public void toString(StringBuilder builder) {
        builder.append("{ ");
        builder.append("IdColumn=");
        builder.append(mIdColumn);
        builder.append(", FromTemplate=");
        builder.append(mFromTemplate);
        builder.append(", ");
        for (String key : this.keySet()) {
            builder.append(key);
            builder.append("=");
            builder.append(this.getAsString(key));
            builder.append(", ");
        }
        builder.append("}");
    }

    /**
     * Check if the given {@link ValuesDelta} is both a subset of this
     * object, and any defined keys have equal values.
     */
    public boolean subsetEquals(ValuesDelta other) {
        for (String key : this.keySet()) {
            final String ourValue = this.getAsString(key);
            final String theirValue = other.getAsString(key);
            if (ourValue == null) {
                // If they have value when we're null, no match
                if (theirValue != null) return false;
            } else {
                // If both values defined and aren't equal, no match
                if (!ourValue.equals(theirValue)) return false;
            }
        }
        // All values compared and matched
        return true;
    }

    /**
     * Build a {@link android.content.ContentProviderOperation} that will transform our
     * "before" state into our "after" state, using insert, update, or
     * delete as needed.
     */
    public ContentProviderOperation.Builder buildDiff(Uri targetUri) {
        return buildDiffHelper(targetUri);
    }

    /**
     * For compatibility purpose.
     */
    public BuilderWrapper buildDiffWrapper(Uri targetUri) {
        final ContentProviderOperation.Builder builder = buildDiffHelper(targetUri);
        BuilderWrapper bw = null;
        if (isInsert()) {
            bw = new BuilderWrapper(builder, CompatUtils.TYPE_INSERT);
        } else if (isDelete()) {
            bw = new BuilderWrapper(builder, CompatUtils.TYPE_DELETE);
        } else if (isUpdate()) {
            bw = new BuilderWrapper(builder, CompatUtils.TYPE_UPDATE);
        }
        return bw;
    }

    private ContentProviderOperation.Builder buildDiffHelper(Uri targetUri) {
        ContentProviderOperation.Builder builder = null;
        if (isInsert()) {
            // Changed values are "insert" back-referenced to Contact
            mAfter.remove(mIdColumn);
            builder = ContentProviderOperation.newInsert(targetUri);
            builder.withValues(mAfter);
        } else if (isDelete()) {
            // When marked for deletion and "before" exists, then "delete"
            builder = ContentProviderOperation.newDelete(targetUri);
            builder.withSelection(mIdColumn + "=" + getId(), null);
        } else if (isUpdate()) {
            // When has changes and "before" exists, then "update"
            builder = ContentProviderOperation.newUpdate(targetUri);
            builder.withSelection(mIdColumn + "=" + getId(), null);
            builder.withValues(mAfter);
        }
        return builder;
    }

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

    /** {@inheritDoc} */
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeParcelable(mBefore, flags);
        dest.writeParcelable(mAfter, flags);
        dest.writeString(mIdColumn);
    }

    public void readFromParcel(Parcel source) {
        final ClassLoader loader = getClass().getClassLoader();
        mBefore = source.<ContentValues> readParcelable(loader);
        mAfter = source.<ContentValues> readParcelable(loader);
        mIdColumn = source.readString();
    }

    public static final Creator<ValuesDelta> CREATOR = new Creator<ValuesDelta>() {
        public ValuesDelta createFromParcel(Parcel in) {
            final ValuesDelta values = new ValuesDelta();
            values.readFromParcel(in);
            return values;
        }

        public ValuesDelta[] newArray(int size) {
            return new ValuesDelta[size];
        }
    };

    public void setGroupRowId(long groupId) {
        put(ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID, groupId);
    }

    public Long getGroupRowId() {
        return getAsLong(ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID);
    }

    public void setPhoto(byte[] value) {
        put(ContactsContract.CommonDataKinds.Photo.PHOTO, value);
    }

    public byte[] getPhoto() {
        return getAsByteArray(ContactsContract.CommonDataKinds.Photo.PHOTO);
    }

    public void setSuperPrimary(boolean val) {
        if (val) {
            put(ContactsContract.Data.IS_SUPER_PRIMARY, 1);
        } else {
            put(ContactsContract.Data.IS_SUPER_PRIMARY, 0);
        }
    }

    public void setPhoneticFamilyName(String value) {
        put(ContactsContract.CommonDataKinds.StructuredName.PHONETIC_FAMILY_NAME, value);
    }

    public void setPhoneticMiddleName(String value) {
        put(ContactsContract.CommonDataKinds.StructuredName.PHONETIC_MIDDLE_NAME, value);
    }

    public void setPhoneticGivenName(String value) {
        put(ContactsContract.CommonDataKinds.StructuredName.PHONETIC_GIVEN_NAME, value);
    }

    public String getPhoneticFamilyName() {
        return getAsString(ContactsContract.CommonDataKinds.StructuredName.PHONETIC_FAMILY_NAME);
    }

    public String getPhoneticMiddleName() {
        return getAsString(ContactsContract.CommonDataKinds.StructuredName.PHONETIC_MIDDLE_NAME);
    }

    public String getPhoneticGivenName() {
        return getAsString(ContactsContract.CommonDataKinds.StructuredName.PHONETIC_GIVEN_NAME);
    }

    public String getDisplayName() {
        return getAsString(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME);
    }

    public void setDisplayName(String name) {
        if (name == null) {
            putNull(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME);
        } else {
            put(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name);
        }
    }

    public void copyStructuredNameFieldsFrom(ValuesDelta name) {
        copyStringFrom(name, ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME);

        copyStringFrom(name, ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME);
        copyStringFrom(name, ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME);
        copyStringFrom(name, ContactsContract.CommonDataKinds.StructuredName.PREFIX);
        copyStringFrom(name, ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME);
        copyStringFrom(name, ContactsContract.CommonDataKinds.StructuredName.SUFFIX);

        copyStringFrom(name, ContactsContract.CommonDataKinds.StructuredName.PHONETIC_GIVEN_NAME);
        copyStringFrom(name, ContactsContract.CommonDataKinds.StructuredName.PHONETIC_MIDDLE_NAME);
        copyStringFrom(name, ContactsContract.CommonDataKinds.StructuredName.PHONETIC_FAMILY_NAME);

        copyStringFrom(name, ContactsContract.CommonDataKinds.StructuredName.FULL_NAME_STYLE);
        copyStringFrom(name, ContactsContract.Data.DATA11);
    }

    public String getPhoneNumber() {
        return getAsString(ContactsContract.CommonDataKinds.Phone.NUMBER);
    }

    public String getPhoneNormalizedNumber() {
        return getAsString(ContactsContract.CommonDataKinds.Phone.NORMALIZED_NUMBER);
    }

    public boolean hasPhoneType() {
        return getPhoneType() != null;
    }

    public Integer getPhoneType() {
        return getAsInteger(ContactsContract.CommonDataKinds.Phone.TYPE);
    }

    public String getPhoneLabel() {
        return getAsString(ContactsContract.CommonDataKinds.Phone.LABEL);
    }

    public String getEmailData() {
        return getAsString(ContactsContract.CommonDataKinds.Email.DATA);
    }

    public boolean hasEmailType() {
        return getEmailType() != null;
    }

    public Integer getEmailType() {
        return getAsInteger(ContactsContract.CommonDataKinds.Email.TYPE);
    }

    public String getEmailLabel() {
        return getAsString(ContactsContract.CommonDataKinds.Email.LABEL);
    }
}
