/*
 * 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 android.provider.cts.contacts;

import com.google.android.collect.Lists;
import com.google.android.collect.Sets;

import android.content.ContentProviderClient;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.provider.BaseColumns;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.Groups;
import android.provider.ContactsContract.RawContacts;
import android.text.TextUtils;

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

import junit.framework.Assert;
import junit.framework.ComparisonFailure;

/**
 * A test data builder for ContactsContract tests.
 */
public class ContactsContract_TestDataBuilder {
    private ContentProviderClient mProvider;
    private ArrayList<Builder<?>> mCreatedRows = Lists.newArrayList();
    private HashSet<Builder<?>> mLoadedRows = Sets.newHashSet();

    private interface IdQuery {
        String[] COLUMNS = new String[] {
            BaseColumns._ID,
        };

        int _ID = 0;
    }

    public abstract class  Builder<T extends Builder<?>> extends Assert {
        protected ContentValues mValues = new ContentValues();
        private Uri mUri;
        private long mId = -1;
        private Cursor mCursor;
        private boolean mAlreadyDeleted;

        protected abstract Uri getContentUri();

        public long getId() throws Exception {
            if (mId != -1) {
                return mId;
            }

            assertNotNull("Row has not be inserted or loaded yet", mUri);

            Cursor cursor = mProvider.query(mUri, IdQuery.COLUMNS, null, null, null, null);
            if (cursor != null) {
                try {
                    cursor.moveToFirst();
                    mId = cursor.getInt(IdQuery._ID);
                } finally {
                    cursor.close();
                }

            }
            assertTrue("Could not obtain _ID for URI: " + mUri, mId != -1);
            return mId;
        }

        @SuppressWarnings("unchecked")
        public T setUri(Uri uri) {
            mUri = uri;
            return (T)this;
        }

        public Uri getUri() {
            if (mUri == null) {
                assertTrue("Neither URI nor ID has been specified", mId != -1);
                mUri = ContentUris.withAppendedId(getContentUri(), mId);
            }
            return mUri;
        }

        @SuppressWarnings("unchecked")
        public T with(String key, String value) {
            mValues.put(key, value);
            return (T)this;
        }

        @SuppressWarnings("unchecked")
        public T with(String key, long value) {
            mValues.put(key, value);
            return (T)this;
        }

        @SuppressWarnings("unchecked")
        public T with(String key, byte[] value) {
            mValues.put(key, value);
            return (T)this;
        }

        @SuppressWarnings("unchecked")
        public T insert() throws Exception {
            insertDependent();
            mCreatedRows.add(this);
            return (T)this;
        }

        @SuppressWarnings("unchecked")
        public T insertDependent() throws Exception {
            mUri = mProvider.insert(getContentUri(), mValues);
            assertNotNull("Could not insert a row in " + getContentUri(), mUri);
            mId = ContentUris.parseId(mUri);
            return (T)this;
        }

        public void delete() throws Exception {
            int count = mProvider.delete(getUri(), null, null);
            assertEquals("Wrong number of rows deleted for " + getUri(), 1, count);
        }

        public void deletePermanently() throws Exception {
            if (mAlreadyDeleted) {
                return;
            }
            Uri uri = getUri().buildUpon()
                    .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
                    .build();
            int count = mProvider.delete(uri, null, null);
            assertEquals("Wrong number of rows deleted for " + uri, 1, count);
            mCreatedRows.remove(this);
        }

        @SuppressWarnings("unchecked")
        public T load() throws Exception {
            close();
            mLoadedRows.add(this);

            mCursor = mProvider.query(getUri(), null, null, null, null, null);
            if (mCursor == null || !mCursor.moveToFirst()) {
                return null;
            } else {
                return (T) this;
            }
        }

        @SuppressWarnings("unchecked")
        public T loadUsingValues() throws Exception {
            close();
            mLoadedRows.add(this);

            StringBuilder selection = new StringBuilder();
            ArrayList<String> selectionArgs = Lists.newArrayList();
            Set<Map.Entry<String, Object>> entries = mValues.valueSet();
            for (Map.Entry<String, Object> entry : entries) {
                String column = entry.getKey();
                Object value = entry.getValue();

                if (selection.length() != 0) {
                    selection.append(" AND ");
                }

                selection.append(column);
                if (value == null) {
                    selection.append(" NOT NULL");
                } else {
                    selection.append("=?");
                    selectionArgs.add(value.toString());
                }
            }
            mCursor = mProvider.query(getContentUri(), null,
                    selection.toString(),
                    selectionArgs.toArray(new String[0]), null, null);
            if (mCursor == null || !mCursor.moveToFirst()) {
                fail("No data rows for " + getContentUri() + "[" + mValues.toString() + "]");
            }
            mId = mCursor.getLong(getColumnIndex(BaseColumns._ID));
            return (T)this;
        }

        public boolean isNull(String columnName) {
            return mCursor.isNull(mCursor.getColumnIndex(columnName));
        }

        public long getLong(String columnName) {
            return mCursor.getLong(mCursor.getColumnIndex(columnName));
        }

        public String getString(String columnName) {
            return mCursor.getString(mCursor.getColumnIndex(columnName));
        }

        public void assertColumn(String columnName, long value) {
            assertEquals(value, mCursor.getLong(getColumnIndex(columnName)));
        }

        public void assertColumn(String columnName, String value) {
            assertEquals(value, mCursor.getString(getColumnIndex(columnName)));
        }

        public void assertColumn(String columnName, byte[] value) {
            assertEquals(value, mCursor.getBlob(getColumnIndex(columnName)));
        }

        public void assertBlobColumnNotNull(String columnName) {
            assertNotNull(mCursor.getBlob(getColumnIndex(columnName)));
        }

        public void assertBlobColumnNull(String columnName) {
            assertNull(mCursor.getBlob(getColumnIndex(columnName)));
        }

        public void assertEquals(byte[] expected, byte[] actual) {
            assertEquals(null, expected, actual);
        }

        public void assertEquals(String message, byte[] expected, byte[] actual) {
            if (expected == null && actual == null)
                return;
            if (expected != null && Arrays.equals(actual, expected))
                return;
            throw new ComparisonFailure(message, expected.toString(), actual.toString());
        }

        private int getColumnIndex(String columnName) {
            int index = mCursor.getColumnIndex(columnName);
            assertTrue("No such column: " + columnName +
                    ". Available columns: " + TextUtils.join(", ", mCursor.getColumnNames()),
                    index != -1);
            return index;
        }

        public void close() {
            if (mCursor != null) {
                mCursor.close();
                mCursor = null;
            }
            mLoadedRows.remove(this);
        }

        public void setAlreadyDeleted() {
            mAlreadyDeleted = true;
        }
    }

    public class TestRawContact extends Builder<TestRawContact> {

        private TestContact mContact;

        @Override
        protected Uri getContentUri() {
            return RawContacts.CONTENT_URI;
        }

        public TestData newDataRow(String mimeType) {
            return new TestData(this, mimeType);
        }

        public long getContactId() {
            return getLong(RawContacts.CONTACT_ID);
        }

        public TestContact getContact() throws Exception {
            if (mContact == null) {
                mContact = new NestedTestContact(this);
            }
            return mContact;
        }
    }

    public class TestContact extends Builder<TestContact> {

        @Override
        protected Uri getContentUri() {
            return Contacts.CONTENT_URI;
        }
    }

    private class NestedTestContact extends TestContact {
        private final TestRawContact mRawContact;

        public NestedTestContact(TestRawContact rawContact) {
            mRawContact = rawContact;
        }

        @Override
        public long getId() throws Exception {
            return mRawContact.getContactId();
        }

        @Override
        public TestContact load() throws Exception {
            return with(Contacts._ID, mRawContact.getContactId()).loadUsingValues();
        }
    }

    public class TestGroup extends Builder<TestGroup> {

        @Override
        protected Uri getContentUri() {
            return Groups.CONTENT_URI;
        }
    }

    public class TestData extends Builder<TestData> {
        private final TestRawContact mRawContact;

        public TestData(TestRawContact rawContact, String mimeType) {
            this.mRawContact = rawContact;
            mValues.put(Data.MIMETYPE, mimeType);
        }

        @Override
        protected Uri getContentUri() {
            return Data.CONTENT_URI;
        }

        @Override
        public TestData insert() throws Exception {
            mValues.put(Data.RAW_CONTACT_ID, mRawContact.getId());
            return super.insertDependent();
        }

        public long getRawContactId() {
            return getLong(Data.RAW_CONTACT_ID);
        }

        public long getId() {
            return getLong(Data._ID);
        }

        public TestRawContact getRawContact() throws Exception {
            return mRawContact;
        }
    }

    public ContactsContract_TestDataBuilder(ContentProviderClient provider) {
        this.mProvider = provider;
    }

    public TestRawContact newRawContact() {
        return new TestRawContact();
    }

    public TestContact newContact() {
        return new TestContact();
    }

    public TestGroup newGroup() {
        return new TestGroup();
    }

    public void cleanup() throws Exception {
        for (Builder<?> builder : new ArrayList<Builder<?>>(mCreatedRows)) {
            builder.deletePermanently();
        }

        for (Builder<?> builder : new HashSet<Builder<?>>(mLoadedRows)) {
            builder.close();
        }
    }

}
