/*
 * Copyright (C) 2008 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.database.cts;


import android.content.Context;
import android.database.AbstractCursor;
import android.database.CharArrayBuffer;
import android.database.ContentObserver;
import android.database.CursorIndexOutOfBoundsException;
import android.database.CursorWindow;
import android.database.DataSetObserver;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.Bundle;
import android.test.InstrumentationTestCase;

import java.io.File;
import java.util.ArrayList;
import java.util.Random;

/**
 * Test {@link AbstractCursor}.
 */
public class AbstractCursorTest extends InstrumentationTestCase {
    private static final int POSITION0 = 0;
    private static final int POSITION1 = 1;
    private  static final int ROW_MAX = 10;
    private static final int DATA_COUNT = 10;
    private static final String[] COLUMN_NAMES1 = new String[] {
        "_id",             // 0
        "number"           // 1
    };
    private static final String[] COLUMN_NAMES = new String[] { "name", "number", "profit" };
    private TestAbstractCursor mTestAbstractCursor;
    private Object mLockObj = new Object();

    private SQLiteDatabase mDatabase;
    private File mDatabaseFile;
    private AbstractCursor mDatabaseCursor;

    @Override
    protected void setUp() throws Exception {
        super.setUp();

        setupDatabase();
        ArrayList<ArrayList> list = createTestList(ROW_MAX, COLUMN_NAMES.length);
        mTestAbstractCursor = new TestAbstractCursor(COLUMN_NAMES, list);
    }

    @Override
    protected void tearDown() throws Exception {
        mDatabaseCursor.close();
        mTestAbstractCursor.close();
        mDatabase.close();
        if (mDatabaseFile.exists()) {
            mDatabaseFile.delete();
        }
        super.tearDown();
    }

    public void testConstructor() {
        TestAbstractCursor abstractCursor = new TestAbstractCursor();
        assertEquals(-1, abstractCursor.getPosition());
    }

    public void testGetBlob() {
        try {
            mTestAbstractCursor.getBlob(0);
            fail("getBlob should throws a UnsupportedOperationException here");
        } catch (UnsupportedOperationException e) {
            // expected
        }
    }

    public void testRegisterDataSetObserver() {
        MockDataSetObserver datasetObserver = new MockDataSetObserver();

        try {
            mDatabaseCursor.unregisterDataSetObserver(datasetObserver);
            fail("Can't unregister DataSetObserver before it is registered.");
        } catch (IllegalStateException e) {
            // expected
        }

        mDatabaseCursor.registerDataSetObserver(datasetObserver);

        try {
            mDatabaseCursor.registerDataSetObserver(datasetObserver);
            fail("Can't register DataSetObserver twice before unregister it.");
        } catch (IllegalStateException e) {
            // expected
        }

        mDatabaseCursor.unregisterDataSetObserver(datasetObserver);
        mDatabaseCursor.registerDataSetObserver(datasetObserver);
    }

    public void testRegisterContentObserver() {
        MockContentObserver contentObserver = new MockContentObserver();

        try {
            mDatabaseCursor.unregisterContentObserver(contentObserver);
            fail("Can't unregister ContentObserver before it is registered.");
        } catch (IllegalStateException e) {
            // expected
        }

        mDatabaseCursor.registerContentObserver(contentObserver);

        try {
            mDatabaseCursor.registerContentObserver(contentObserver);
            fail("Can't register DataSetObserver twice before unregister it.");
        } catch (IllegalStateException e) {
            // expected
        }

        mDatabaseCursor.unregisterContentObserver(contentObserver);
        mDatabaseCursor.registerContentObserver(contentObserver);
    }

    public void testSetNotificationUri() {
        String MOCK_URI = "content://abstractrcursortest/testtable";
        mDatabaseCursor.setNotificationUri(getInstrumentation().getContext().getContentResolver(),
                Uri.parse(MOCK_URI));
    }

    public void testRespond() {
        Bundle b = new Bundle();
        Bundle bundle = mDatabaseCursor.respond(b);
        assertSame(Bundle.EMPTY, bundle);

        bundle = mDatabaseCursor.respond(null);
        assertSame(Bundle.EMPTY, bundle);
    }

    public void testRequery() {
        MockDataSetObserver mock = new MockDataSetObserver();
        mDatabaseCursor.registerDataSetObserver(mock);
        assertFalse(mock.hadCalledOnChanged());
        mDatabaseCursor.requery();
        assertTrue(mock.hadCalledOnChanged());
    }

    public void testOnChange() throws InterruptedException {
        MockContentObserver mock = new MockContentObserver();
        mTestAbstractCursor.registerContentObserver(mock);
        assertFalse(mock.hadCalledOnChange());
        mTestAbstractCursor.onChange(true);
        synchronized(mLockObj) {
            if ( !mock.hadCalledOnChange() ) {
                mLockObj.wait(5000);
            }
        }
        assertTrue(mock.hadCalledOnChange());
    }

    public void testOnMove() {
        mTestAbstractCursor.resetOnMoveRet();
        assertFalse(mTestAbstractCursor.getOnMoveRet());
        mTestAbstractCursor.moveToFirst();
        mTestAbstractCursor.moveToPosition(5);
        assertTrue(mTestAbstractCursor.getOnMoveRet());
        assertEquals(0, mTestAbstractCursor.getOldPos());
        assertEquals(5, mTestAbstractCursor.getNewPos());
    }

    public void testMoveToPrevious() {
        // Test moveToFirst, isFirst, moveToNext, getPosition
        assertTrue(mDatabaseCursor.moveToFirst());
        assertTrue(mDatabaseCursor.isFirst());
        assertEquals(0, mDatabaseCursor.getPosition());
        assertTrue(mDatabaseCursor.moveToNext());
        assertEquals(1, mDatabaseCursor.getPosition());
        assertFalse(mDatabaseCursor.isFirst());
        assertTrue(mDatabaseCursor.moveToNext());
        assertEquals(2, mDatabaseCursor.getPosition());

        // invoke moveToPosition with a number larger than row count.
        assertFalse(mDatabaseCursor.moveToPosition(30000));
        assertEquals(mDatabaseCursor.getCount(), mDatabaseCursor.getPosition());

        assertFalse(mDatabaseCursor.moveToPosition(-1));
        assertEquals(-1, mDatabaseCursor.getPosition());
        assertTrue(mDatabaseCursor.isBeforeFirst());

        mDatabaseCursor.moveToPosition(5);
        assertEquals(5, mDatabaseCursor.getPosition());

        // Test moveToPrevious
        assertTrue(mDatabaseCursor.moveToPrevious());
        assertEquals(4, mDatabaseCursor.getPosition());
        assertTrue(mDatabaseCursor.moveToPrevious());
        assertEquals(3, mDatabaseCursor.getPosition());
        assertTrue(mDatabaseCursor.moveToPrevious());
        assertEquals(2, mDatabaseCursor.getPosition());

        // Test moveToLast, isLast, moveToPrevius, isAfterLast.
        assertFalse(mDatabaseCursor.isLast());
        assertTrue(mDatabaseCursor.moveToLast());
        assertTrue(mDatabaseCursor.isLast());
        assertFalse(mDatabaseCursor.isAfterLast());

        assertFalse(mDatabaseCursor.moveToNext());
        assertTrue(mDatabaseCursor.isAfterLast());
        assertFalse(mDatabaseCursor.moveToNext());
        assertTrue(mDatabaseCursor.isAfterLast());
        assertFalse(mDatabaseCursor.isLast());
        assertTrue(mDatabaseCursor.moveToPrevious());
        assertTrue(mDatabaseCursor.isLast());
        assertTrue(mDatabaseCursor.moveToPrevious());
        assertFalse(mDatabaseCursor.isLast());

        // Test move(int).
        mDatabaseCursor.moveToFirst();
        assertEquals(0, mDatabaseCursor.getPosition());
        assertFalse(mDatabaseCursor.move(-1));
        assertEquals(-1, mDatabaseCursor.getPosition());
        assertTrue(mDatabaseCursor.move(1));
        assertEquals(0, mDatabaseCursor.getPosition());

        assertTrue(mDatabaseCursor.move(5));
        assertEquals(5, mDatabaseCursor.getPosition());
        assertTrue(mDatabaseCursor.move(-1));
        assertEquals(4, mDatabaseCursor.getPosition());

        mDatabaseCursor.moveToLast();
        assertTrue(mDatabaseCursor.isLast());
        assertFalse(mDatabaseCursor.isAfterLast());
        assertFalse(mDatabaseCursor.move(1));
        assertFalse(mDatabaseCursor.isLast());
        assertTrue(mDatabaseCursor.isAfterLast());
        assertTrue(mDatabaseCursor.move(-1));
        assertTrue(mDatabaseCursor.isLast());
        assertFalse(mDatabaseCursor.isAfterLast());
    }

    public void testIsClosed() {
        assertFalse(mDatabaseCursor.isClosed());
        mDatabaseCursor.close();
        assertTrue(mDatabaseCursor.isClosed());
    }

    public void testGetWindow() {
        CursorWindow window = new CursorWindow(false);
        assertEquals(0, window.getNumRows());
        // fill window from position 0
        mDatabaseCursor.fillWindow(0, window);

        assertNotNull(mDatabaseCursor.getWindow());
        assertEquals(mDatabaseCursor.getCount(), window.getNumRows());

        while (mDatabaseCursor.moveToNext()) {
            assertEquals(mDatabaseCursor.getInt(POSITION1),
                    window.getInt(mDatabaseCursor.getPosition(), POSITION1));
        }
        window.clear();
    }

    public void testGetWantsAllOnMoveCalls() {
        assertFalse(mDatabaseCursor.getWantsAllOnMoveCalls());
    }

    public void testIsFieldUpdated() {
        mTestAbstractCursor.moveToFirst();
        assertFalse(mTestAbstractCursor.isFieldUpdated(0));
    }

    public void testGetUpdatedField() {
        mTestAbstractCursor.moveToFirst();
        assertNull(mTestAbstractCursor.getUpdatedField(0));
    }

    public void testGetExtras() {
        assertSame(Bundle.EMPTY, mDatabaseCursor.getExtras());
    }

    public void testGetCount() {
        assertEquals(DATA_COUNT, mDatabaseCursor.getCount());
    }

    public void testGetColumnNames() {
        String[] names = mDatabaseCursor.getColumnNames();
        assertEquals(COLUMN_NAMES1.length, names.length);

        for (int i = 0; i < COLUMN_NAMES1.length; i++) {
            assertEquals(COLUMN_NAMES1[i], names[i]);
        }
    }

    public void testGetColumnName() {
        assertEquals(COLUMN_NAMES1[0], mDatabaseCursor.getColumnName(0));
        assertEquals(COLUMN_NAMES1[1], mDatabaseCursor.getColumnName(1));
    }

    public void testGetColumnIndexOrThrow() {
        final String COLUMN_FAKE = "fake_name";
        assertEquals(POSITION0, mDatabaseCursor.getColumnIndex(COLUMN_NAMES1[POSITION0]));
        assertEquals(POSITION1, mDatabaseCursor.getColumnIndex(COLUMN_NAMES1[POSITION1]));
        assertEquals(POSITION0, mDatabaseCursor.getColumnIndexOrThrow(COLUMN_NAMES1[POSITION0]));
        assertEquals(POSITION1, mDatabaseCursor.getColumnIndexOrThrow(COLUMN_NAMES1[POSITION1]));

        try {
            mDatabaseCursor.getColumnIndexOrThrow(COLUMN_FAKE);
            fail("IllegalArgumentException expected, but not thrown");
        } catch (IllegalArgumentException expected) {
            // expected
        }
    }

    public void testGetColumnIndex() {
        assertEquals(POSITION0, mDatabaseCursor.getColumnIndex(COLUMN_NAMES1[POSITION0]));
        assertEquals(POSITION1, mDatabaseCursor.getColumnIndex(COLUMN_NAMES1[POSITION1]));
    }

    public void testGetColumnCount() {
        assertEquals(COLUMN_NAMES1.length, mDatabaseCursor.getColumnCount());
    }

    public void testDeactivate() {
        MockDataSetObserver mock = new MockDataSetObserver();
        mDatabaseCursor.registerDataSetObserver(mock);
        assertFalse(mock.hadCalledOnInvalid());
        mDatabaseCursor.deactivate();
        assertTrue(mock.hadCalledOnInvalid());
    }

    public void testCopyStringToBuffer() {
        CharArrayBuffer ca = new CharArrayBuffer(1000);
        mTestAbstractCursor.moveToFirst();
        mTestAbstractCursor.copyStringToBuffer(0, ca);
        CursorWindow window = new CursorWindow(false);
        mTestAbstractCursor.fillWindow(0, window);

        StringBuffer sb = new StringBuffer();
        sb.append(window.getString(0, 0));
        String str = mTestAbstractCursor.getString(0);
        assertEquals(str.length(), ca.sizeCopied);
        assertEquals(sb.toString(), new String(ca.data, 0, ca.sizeCopied));
    }

    public void testCheckPosition() {
        // Test with position = -1.
        try {
            mTestAbstractCursor.checkPosition();
            fail("copyStringToBuffer() should throws CursorIndexOutOfBoundsException here.");
        } catch (CursorIndexOutOfBoundsException e) {
            // expected
        }

        // Test with position = count.
        assertTrue(mTestAbstractCursor.moveToPosition(mTestAbstractCursor.getCount() - 1));
        mTestAbstractCursor.checkPosition();

        try {
            assertFalse(mTestAbstractCursor.moveToPosition(mTestAbstractCursor.getCount()));
            assertEquals(mTestAbstractCursor.getCount(), mTestAbstractCursor.getPosition());
            mTestAbstractCursor.checkPosition();
            fail("copyStringToBuffer() should throws CursorIndexOutOfBoundsException here.");
        } catch (CursorIndexOutOfBoundsException e) {
            // expected
        }
    }

    @SuppressWarnings("unchecked")
    private static ArrayList<ArrayList> createTestList(int rows, int cols) {
        ArrayList<ArrayList> list = new ArrayList<ArrayList>();
        Random ran = new Random();

        for (int i = 0; i < rows; i++) {
            ArrayList<Integer> col = new ArrayList<Integer>();
            list.add(col);

            for (int j = 0; j < cols; j++) {
                // generate random number
                Integer r = ran.nextInt();
                col.add(r);
            }
        }

        return list;
    }

    private void setupDatabase() {
        File dbDir = getInstrumentation().getTargetContext().getDir("tests",
                Context.MODE_WORLD_WRITEABLE);
        mDatabaseFile = new File(dbDir, "database_test.db");
        if (mDatabaseFile.exists()) {
            mDatabaseFile.delete();
        }
        mDatabase = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile.getPath(), null);
        assertNotNull(mDatabaseFile);
        mDatabase.execSQL("CREATE TABLE test1 (_id INTEGER PRIMARY KEY, number TEXT);");
        generateData();
        mDatabaseCursor = (AbstractCursor) mDatabase.query("test1", null, null, null, null, null,
                null);
    }

    private void generateData() {
        for ( int i = 0; i < DATA_COUNT; i++) {
            mDatabase.execSQL("INSERT INTO test1 (number) VALUES ('" + i + "');");
        }
    }

    private class TestAbstractCursor extends AbstractCursor {
        private boolean mOnMoveReturnValue;
        private int mOldPosition;
        private int mNewPosition;
        private String[] mColumnNames;
        private ArrayList<Object>[] mRows;
        private boolean mHadCalledOnChange = false;

        public TestAbstractCursor() {
            super();
        }
        @SuppressWarnings("unchecked")
        public TestAbstractCursor(String[] columnNames, ArrayList<ArrayList> rows) {
            int colCount = columnNames.length;
            boolean foundID = false;
            mRowIdColumnIndex = 0;

            // Add an _id column if not in columnNames
            for (int i = 0; i < colCount; ++i) {
                if (columnNames[i].compareToIgnoreCase("_id") == 0) {
                    mColumnNames = columnNames;
                    foundID = true;
                    break;
                }
            }

            if (!foundID) {
                mColumnNames = new String[colCount + 1];
                System.arraycopy(columnNames, 0, mColumnNames, 0, columnNames.length);
                mColumnNames[colCount] = "_id";
            }

            int rowCount = rows.size();
            mRows = new ArrayList[rowCount];

            for (int i = 0; i < rowCount; ++i) {
                mRows[i] = rows.get(i);

                if (!foundID) {
                    mRows[i].add(Long.valueOf(i));
                }
            }
        }

        public boolean getOnMoveRet() {
            return mOnMoveReturnValue;
        }

        public void resetOnMoveRet() {
            mOnMoveReturnValue = false;
        }

        public int getOldPos() {
            return mOldPosition;
        }

        public int getNewPos() {
            return mNewPosition;
        }

        @Override
        public boolean onMove(int oldPosition, int newPosition) {
            mOnMoveReturnValue = super.onMove(oldPosition, newPosition);
            mOldPosition = oldPosition;
            mNewPosition = newPosition;
            return mOnMoveReturnValue;
        }

        @Override
        public int getCount() {
            return mRows.length;
        }

        @Override
        public String[] getColumnNames() {
            return mColumnNames;
        }

        @Override
        public String getString(int columnIndex) {
            Object cell = mRows[mPos].get(columnIndex);
            return (cell == null) ? null : cell.toString();
        }

        @Override
        public short getShort(int columnIndex) {
            Number num = (Number) mRows[mPos].get(columnIndex);
            return num.shortValue();
        }

        @Override
        public int getInt(int columnIndex) {
            Number num = (Number) mRows[mPos].get(columnIndex);
            return num.intValue();
        }

        @Override
        public long getLong(int columnIndex) {
            Number num = (Number) mRows[mPos].get(columnIndex);
            return num.longValue();
        }

        @Override
        public float getFloat(int columnIndex) {
            Number num = (Number) mRows[mPos].get(columnIndex);
            return num.floatValue();
        }

        @Override
        public double getDouble(int columnIndex) {
            Number num = (Number) mRows[mPos].get(columnIndex);
            return num.doubleValue();
        }

        @Override
        public boolean isNull(int column) {
            return false;
        }

        public boolean hadCalledOnChange() {
            return mHadCalledOnChange;
        }

        // the following are protected methods
        @Override
        protected void checkPosition() {
            super.checkPosition();
        }

        @Override
        protected Object getUpdatedField(int columnIndex) {
            return super.getUpdatedField(columnIndex);
        }

        @Override
        protected boolean isFieldUpdated(int columnIndex) {
            return super.isFieldUpdated(columnIndex);
        }

        @Override
        protected void onChange(boolean selfChange) {
            super.onChange(selfChange);
            mHadCalledOnChange = true;
        }
    }

    private class MockContentObserver extends ContentObserver {
        public boolean mHadCalledOnChange;

        public MockContentObserver() {
            super(null);
        }

        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
            mHadCalledOnChange = true;
            synchronized(mLockObj) {
                mLockObj.notify();
            }
        }

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

        public boolean hadCalledOnChange() {
            return mHadCalledOnChange;
        }
    }

    private class MockDataSetObserver extends DataSetObserver {
        private boolean mHadCalledOnChanged;
        private boolean mHadCalledOnInvalid;

        @Override
        public void onChanged() {
            super.onChanged();
            mHadCalledOnChanged = true;
        }

        @Override
        public void onInvalidated() {
            super.onInvalidated();
            mHadCalledOnInvalid = true;
        }

        public boolean hadCalledOnChanged() {
            return mHadCalledOnChanged;
        }

        public boolean hadCalledOnInvalid() {
            return mHadCalledOnInvalid;
        }
    }
}
