/*
 * 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;

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

import android.content.ContentUris;
import android.content.ContentValues;
import android.content.IContentProvider;
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.HashSet;
import java.util.Map;
import java.util.Set;

import junit.framework.Assert;

/**
 * A test data builder for ContactsContract tests.
 */
public class ContactsContract_TestDataBuilder {
    private IContentProvider 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;

        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);
            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 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 {
            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);
            if (mCursor == null || !mCursor.moveToFirst()) {
                fail("No data rows for URI: " + getUri());
            }
            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);
            if (mCursor == null || !mCursor.moveToFirst()) {
                fail("No data rows for " + getContentUri() + "[" + mValues.toString() + "]");
            }
            mId = mCursor.getLong(getColumnIndex(BaseColumns._ID));
            return (T)this;
        }

        public long getLong(String columnName) {
            return mCursor.getLong(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)));
        }

        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 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 ContactsContract_TestDataBuilder(IContentProvider 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();
        }
    }

}
