/*
 * Copyright (C) 2010 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.test.mocks;

import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.net.Uri;
import android.support.annotation.Nullable;

import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;

import junit.framework.Assert;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * A programmable mock content provider.
 */
public class MockContentProvider extends android.test.mock.MockContentProvider {
    private static final String TAG = "MockContentProvider";

    public static class Query {

        private final Uri mUri;
        private UriMatcher mMatcher;

        private String[] mProjection;
        private String[] mDefaultProjection;
        private String mSelection;
        private String[] mSelectionArgs;
        private String mSortOrder;
        private List<Object> mRows = new ArrayList<>();
        private boolean mAnyProjection;
        private boolean mAnySelection;
        private boolean mAnySortOrder;
        private boolean mAnyNumberOfTimes;

        private boolean mExecuted;

        private Query() {
            mUri = null;
        }

        private Query(UriMatcher matcher) {
            mUri = null;
            mMatcher = matcher;
        }

        public Query(Uri uri) {
            mUri = uri;
        }

        @Override
        public String toString() {
            return queryToString(mUri, mProjection, mSelection, mSelectionArgs, mSortOrder);
        }

        public Query withProjection(String... projection) {
            mProjection = projection;
            return this;
        }

        public Query withDefaultProjection(String... projection) {
            mDefaultProjection = projection;
            return this;
        }

        public Query withAnyProjection() {
            mAnyProjection = true;
            return this;
        }

        public Query withSelection(String selection, String... selectionArgs) {
            mSelection = selection;
            mSelectionArgs = selectionArgs;
            return this;
        }

        public Query withAnySelection() {
            mAnySelection = true;
            return this;
        }

        public Query withSortOrder(String sortOrder) {
            mSortOrder = sortOrder;
            return this;
        }

        public Query withAnySortOrder() {
            mAnySortOrder = true;
            return this;
        }

        public Query returnRow(ContentValues values) {
            mRows.add(values);
            return this;
        }

        public Query returnRow(Object... row) {
            mRows.add(row);
            return this;
        }

        public Query returnEmptyCursor() {
            mRows.clear();
            return this;
        }

        public Query anyNumberOfTimes() {
            mAnyNumberOfTimes = true;
            return this;
        }

        public boolean equals(Uri uri, String[] projection, String selection,
                String[] selectionArgs, String sortOrder) {
            if (mUri == null) {
                if (mMatcher != null && mMatcher.match(uri) == UriMatcher.NO_MATCH) {
                    return false;
                }
            } else if (!uri.equals(mUri)) {
                return false;
            }

            if (!mAnyProjection && !Arrays.equals(projection, mProjection)) {
                return false;
            }

            if (!mAnySelection && !Objects.equals(selection, mSelection)) {
                return false;
            }

            if (!mAnySelection && !Arrays.equals(selectionArgs, mSelectionArgs)) {
                return false;
            }

            if (!mAnySortOrder && !Objects.equals(sortOrder, mSortOrder)) {
                return false;
            }

            return true;
        }

        public Cursor getResult(String[] projection) {
            String[] columnNames;
            if (mAnyProjection) {
                columnNames = projection != null ? projection : mDefaultProjection;
            } else {
                columnNames = mProjection != null ? mProjection : mDefaultProjection;
            }

            MatrixCursor cursor = new MatrixCursor(columnNames);
            for (Object row : mRows) {
                if (row instanceof Object[]) {
                    cursor.addRow((Object[]) row);
                } else {
                    ContentValues values = (ContentValues) row;
                    Object[] columns = new Object[columnNames.length];
                    for (int i = 0; i < columnNames.length; i++) {
                        columns[i] = values.get(columnNames[i]);
                    }
                    cursor.addRow(columns);
                }
            }
            return cursor;
        }

        public static Query forAnyUri() {
            return new Query();
        }

        public static Query forUrisMatching(UriMatcher matcher) {
            return new Query(matcher);
        }

        public static Query forUrisMatching(String authority, String... paths) {
            final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
            for (int i = 0; i < paths.length; i++) {
                matcher.addURI(authority, paths[i], i);
            }
            return new Query(matcher);
        }

    }

    public static class TypeQuery {
        private final Uri mUri;
        private final String mType;

        public TypeQuery(Uri uri, String type) {
            mUri = uri;
            mType = type;
        }

        public Uri getUri() {
            return mUri;
        }

        public String getType() {
            return mType;
        }

        @Override
        public String toString() {
            return mUri + " --> " + mType;
        }

        public boolean equals(Uri uri) {
            return getUri().equals(uri);
        }
    }

    public static class Insert {
        private final Uri mUri;
        private final ContentValues mContentValues;
        private final Uri mResultUri;
        private boolean mAnyNumberOfTimes;
        private boolean mIsExecuted;

        /**
         * Creates a new Insert to expect.
         *
         * @param uri the uri of the insertion request.
         * @param contentValues the ContentValues to insert.
         * @param resultUri the {@link Uri} for the newly inserted item.
         * @throws NullPointerException if any parameter is {@code null}.
         */
        public Insert(Uri uri, ContentValues contentValues, Uri resultUri) {
            mUri = Preconditions.checkNotNull(uri);
            mContentValues = Preconditions.checkNotNull(contentValues);
            mResultUri = Preconditions.checkNotNull(resultUri);
        }

        /**
         * Causes this insert expectation to be useable for mutliple calls to insert, rather than
         * just one.
         *
         * @return this
         */
        public Insert anyNumberOfTimes() {
            mAnyNumberOfTimes = true;
            return this;
        }

        private boolean equals(Uri uri, ContentValues contentValues) {
            return mUri.equals(uri) && mContentValues.equals(contentValues);
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }
            Insert insert = (Insert) o;
            return mAnyNumberOfTimes == insert.mAnyNumberOfTimes &&
                    mIsExecuted == insert.mIsExecuted &&
                    Objects.equals(mUri, insert.mUri) &&
                    Objects.equals(mContentValues, insert.mContentValues) &&
                    Objects.equals(mResultUri, insert.mResultUri);
        }

        @Override
        public int hashCode() {
            return Objects.hash(mUri, mContentValues, mResultUri, mAnyNumberOfTimes, mIsExecuted);
        }

        @Override
        public String toString() {
            return "Insert{" +
                    "mUri=" + mUri +
                    ", mContentValues=" + mContentValues +
                    ", mResultUri=" + mResultUri +
                    ", mAnyNumberOfTimes=" + mAnyNumberOfTimes +
                    ", mIsExecuted=" + mIsExecuted +
                    '}';
        }
    }

    public static class Delete {
        private final Uri mUri;

        private boolean mAnyNumberOfTimes;
        private boolean mAnySelection;
        @Nullable private String mSelection;
        @Nullable private String[] mSelectionArgs;
        private boolean mIsExecuted;
        private int mRowsAffected;

        /**
         * Creates a new Delete to expect.
         * @param uri the uri of the delete request.
         * @throws NullPointerException if uri is {@code null}.
         */
        public Delete(Uri uri) {
            mUri = Preconditions.checkNotNull(uri);
        }

        /**
         * Sets the given information as expected selection arguments.
         *
         * @param selection The selection to expect.
         * @param selectionArgs The selection args to expect.
         * @return this.
         */
        public Delete withSelection(String selection, @Nullable String[] selectionArgs) {
            mSelection = Preconditions.checkNotNull(selection);
            mSelectionArgs = selectionArgs;
            mAnySelection = false;
            return this;
        }

        /**
         * Sets this delete to expect any selection arguments.
         *
         * @return this.
         */
        public Delete withAnySelection() {
            mAnySelection = true;
            return this;
        }

        /**
         * Sets this delete to return the given number of rows affected.
         *
         * @param rowsAffected The value to return when this expected delete is executed.
         * @return this.
         */
        public Delete returnRowsAffected(int rowsAffected) {
            mRowsAffected = rowsAffected;
            return this;
        }

        /**
         * Causes this delete expectation to be useable for multiple calls to delete, rather than
         * just one.
         *
         * @return this.
         */
        public Delete anyNumberOfTimes() {
            mAnyNumberOfTimes = true;
            return this;
        }

        private boolean equals(Uri uri, String selection, String[] selectionArgs) {
            return mUri.equals(uri) && Objects.equals(mSelection, selection)
                    && Arrays.equals(mSelectionArgs, selectionArgs);
        }
    }

    public static class Update {
        private final Uri mUri;
        private final ContentValues mContentValues;
        @Nullable private String mSelection;
        @Nullable private String[] mSelectionArgs;
        private boolean mAnyNumberOfTimes;
        private boolean mIsExecuted;
        private int mRowsAffected;

        /**
         * Creates a new Update to expect.
         *
         * @param uri the uri of the update request.
         * @param contentValues the ContentValues to update.
         *
         * @throws NullPointerException if any parameter is {@code null}.
         */
        public Update(Uri uri,
                      ContentValues contentValues,
                      @Nullable String selection,
                      @Nullable String[] selectionArgs) {
            mUri = Preconditions.checkNotNull(uri);
            mContentValues = Preconditions.checkNotNull(contentValues);
            mSelection = selection;
            mSelectionArgs = selectionArgs;
        }

        /**
         * Causes this update expectation to be useable for mutliple calls to update, rather than
         * just one.
         *
         * @return this
         */
        public Update anyNumberOfTimes() {
            mAnyNumberOfTimes = true;
            return this;
        }

        /**
         * Sets this update to return the given number of rows affected.
         *
         * @param rowsAffected The value to return when this expected update is executed.
         * @return this.
         */
        public Update returnRowsAffected(int rowsAffected) {
            mRowsAffected = rowsAffected;
            return this;
        }

        private boolean equals(Uri uri,
                               ContentValues contentValues,
                               @Nullable String selection,
                               @Nullable String[] selectionArgs) {
            return mUri.equals(uri) && mContentValues.equals(contentValues) &&
                    Objects.equals(mSelection, selection) &&
                    Objects.equals(mSelectionArgs, selectionArgs);
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }
            Update update = (Update) o;
            return mAnyNumberOfTimes == update.mAnyNumberOfTimes &&
                    mIsExecuted == update.mIsExecuted &&
                    Objects.equals(mUri, update.mUri) &&
                    Objects.equals(mContentValues, update.mContentValues) &&
                    Objects.equals(mSelection, update.mSelection) &&
                    Objects.equals(mSelectionArgs, update.mSelectionArgs);
        }

        @Override
        public int hashCode() {
            return Objects.hash(mUri, mContentValues, mAnyNumberOfTimes, mIsExecuted, mSelection,
                    mSelectionArgs);
        }

        @Override
        public String toString() {
            return "Update{" +
                    "mUri=" + mUri +
                    ", mContentValues=" + mContentValues +
                    ", mAnyNumberOfTimes=" + mAnyNumberOfTimes +
                    ", mIsExecuted=" + mIsExecuted +
                    ", mSelection=" + mSelection +
                    ", mSelectionArgs=" + mSelectionArgs +
                    '}';
        }
    }

    private List<Query> mExpectedQueries = new ArrayList<>();
    private Map<Uri, String> mExpectedTypeQueries = Maps.newHashMap();
    private List<Insert> mExpectedInserts = new ArrayList<>();
    private List<Delete> mExpectedDeletes = new ArrayList<>();
    private List<Update> mExpectedUpdates = new ArrayList<>();

    @Override
    public boolean onCreate() {
        return true;
    }

    public Query expect(Query query) {
        mExpectedQueries.add(query);
        return query;
    }

    public Query expectQuery(Uri contentUri) {
        return expect(new Query(contentUri));
    }

    public Query expectQuery(String contentUri) {
        return expectQuery(Uri.parse(contentUri));
    }

    public void expectTypeQuery(Uri uri, String type) {
        mExpectedTypeQueries.put(uri, type);
    }

    public void expectInsert(Uri contentUri, ContentValues contentValues, Uri resultUri) {
        mExpectedInserts.add(new Insert(contentUri, contentValues, resultUri));
    }

    public Update expectUpdate(Uri contentUri,
                               ContentValues contentValues,
                               @Nullable String selection,
                               @Nullable String[] selectionArgs) {
        Update update = new Update(contentUri, contentValues, selection, selectionArgs);
        mExpectedUpdates.add(update);
        return update;
    }

    public Delete expectDelete(Uri contentUri) {
        Delete delete = new Delete(contentUri);
        mExpectedDeletes.add(delete);
        return delete;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
            String sortOrder) {
        if (mExpectedQueries.isEmpty()) {
            Assert.fail("Unexpected query: Actual:"
                    + queryToString(uri, projection, selection, selectionArgs, sortOrder));
        }

        for (Iterator<Query> iterator = mExpectedQueries.iterator(); iterator.hasNext();) {
            Query query = iterator.next();
            if (query.equals(uri, projection, selection, selectionArgs, sortOrder)) {
                query.mExecuted = true;
                if (!query.mAnyNumberOfTimes) {
                    iterator.remove();
                }
                return query.getResult(projection);
            }
        }

        Assert.fail("Incorrect query. Expected one of: " + mExpectedQueries + ". Actual: " +
                queryToString(uri, projection, selection, selectionArgs, sortOrder));
        return null;
    }

    @Override
    public String getType(Uri uri) {
        if (mExpectedTypeQueries.isEmpty()) {
            Assert.fail("Unexpected getType query: " + uri);
        }

        String mimeType = mExpectedTypeQueries.get(uri);
        if (mimeType != null) {
            return mimeType;
        }

        Assert.fail("Unknown mime type for: " + uri);
        return null;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        if (mExpectedInserts.isEmpty()) {
            Assert.fail("Unexpected insert. Actual: " + insertToString(uri, values));
        }
        for (Iterator<Insert> iterator = mExpectedInserts.iterator(); iterator.hasNext(); ) {
            Insert insert = iterator.next();
            if (insert.equals(uri, values)) {
                insert.mIsExecuted = true;
                if (!insert.mAnyNumberOfTimes) {
                    iterator.remove();
                }
                return insert.mResultUri;
            }
        }

        Assert.fail("Incorrect insert. Expected one of: " + mExpectedInserts + ". Actual: "
                + insertToString(uri, values));
        return null;
    }

    private String insertToString(Uri uri, ContentValues contentValues) {
        return "Insert { uri=" + uri + ", contentValues=" + contentValues + '}';
    }

    @Override
    public int update(Uri uri,
                      ContentValues values,
                      @Nullable String selection,
                      @Nullable String[] selectionArgs) {
        if (mExpectedUpdates.isEmpty()) {
            Assert.fail("Unexpected update. Actual: "
                    + updateToString(uri, values, selection, selectionArgs));
        }
        for (Iterator<Update> iterator = mExpectedUpdates.iterator(); iterator.hasNext(); ) {
            Update update = iterator.next();
            if (update.equals(uri, values, selection, selectionArgs)) {
                update.mIsExecuted = true;
                if (!update.mAnyNumberOfTimes) {
                    iterator.remove();
                }
                return update.mRowsAffected;
            }
        }

        Assert.fail("Incorrect update. Expected one of: " + mExpectedUpdates + ". Actual: "
                + updateToString(uri, values, selection, selectionArgs));
        return - 1;
    }

    private String updateToString(Uri uri,
                                  ContentValues contentValues,
                                  @Nullable String selection,
                                  @Nullable String[] selectionArgs) {
        return "Update { uri=" + uri + ", contentValues=" + contentValues + ", selection=" +
                selection + ", selectionArgs" + Arrays.toString(selectionArgs) + '}';
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        if (mExpectedDeletes.isEmpty()) {
            Assert.fail("Unexpected delete. Actual: " + deleteToString(uri, selection,
                    selectionArgs));
        }
        for (Iterator<Delete> iterator = mExpectedDeletes.iterator(); iterator.hasNext(); ) {
            Delete delete = iterator.next();
            if (delete.equals(uri, selection, selectionArgs)) {
                delete.mIsExecuted = true;
                if (!delete.mAnyNumberOfTimes) {
                    iterator.remove();
                }
                return delete.mRowsAffected;
            }
        }
        Assert.fail("Incorrect delete. Expected one of: " + mExpectedDeletes + ". Actual: "
                + deleteToString(uri, selection, selectionArgs));
        return -1;
    }

    private String deleteToString(Uri uri, String selection, String[] selectionArgs) {
        return "Delete { uri=" + uri + ", selection=" + selection + ", selectionArgs"
                + Arrays.toString(selectionArgs) + '}';
    }

    private static String queryToString(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {
        StringBuilder sb = new StringBuilder();
        sb.append(uri == null ? "<Any Uri>" : uri).append(" ");
        if (projection != null) {
            sb.append(Arrays.toString(projection));
        } else {
            sb.append("[]");
        }
        if (selection != null) {
            sb.append(" selection: '").append(selection).append("'");
            if (selectionArgs != null) {
                sb.append(Arrays.toString(selectionArgs));
            } else {
                sb.append("[]");
            }
        }
        if (sortOrder != null) {
            sb.append(" sort: '").append(sortOrder).append("'");
        }
        return sb.toString();
    }

    public void verify() {
        verifyQueries();
        verifyInserts();
        verifyDeletes();
    }

    private void verifyQueries() {
        List<Query> missedQueries = new ArrayList<>();
        for (Query query : mExpectedQueries) {
            if (!query.mExecuted) {
                missedQueries.add(query);
            }
        }
        Assert.assertTrue("Not all expected queries have been called: " + missedQueries,
                missedQueries.isEmpty());
    }

    private void verifyInserts() {
        List<Insert> missedInserts = new ArrayList<>();
        for (Insert insert : mExpectedInserts) {
            if (!insert.mIsExecuted) {
                missedInserts.add(insert);
            }
        }
        Assert.assertTrue("Not all expected inserts have been called: " + missedInserts,
                missedInserts.isEmpty());
    }

    private void verifyDeletes() {
        List<Delete> missedDeletes = new ArrayList<>();
        for (Delete delete : mExpectedDeletes) {
            if (!delete.mIsExecuted) {
                missedDeletes.add(delete);
            }
        }
        Assert.assertTrue("Not all expected deletes have been called: " + missedDeletes,
                missedDeletes.isEmpty());
    }
}
