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


import android.content.Context;
import android.database.AbstractCursor;
import android.database.AbstractWindowedCursor;
import android.database.Cursor;
import android.database.CursorWindow;
import android.database.DataSetObserver;
import android.database.SQLException;
import android.database.StaleDataException;
import android.database.sqlite.SQLiteBlobTooBigException;
import android.database.sqlite.SQLiteCursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDirectCursorDriver;
import android.test.AndroidTestCase;

import java.util.Arrays;

/**
 * Test {@link AbstractCursor}.
 */
public class SQLiteCursorTest extends AndroidTestCase {
    private SQLiteDatabase mDatabase;
    private static final String[] COLUMNS = new String[] { "_id", "number_1", "number_2" };
    private static final String TABLE_NAME = "test";
    private static final String TABLE_COLUMNS = " number_1 INTEGER, number_2 INTEGER";
    private static final int DEFAULT_TABLE_VALUE_BEGINS = 1;
    private static final int TEST_COUNT = 10;
    private static final String TEST_SQL = "SELECT * FROM test ORDER BY number_1";
    private static final String DATABASE_FILE = "database_test.db";

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        getContext().deleteDatabase(DATABASE_FILE);
        mDatabase = getContext().openOrCreateDatabase(DATABASE_FILE, Context.MODE_PRIVATE, null);
        createTable(TABLE_NAME, TABLE_COLUMNS);
        addValuesIntoTable(TABLE_NAME, DEFAULT_TABLE_VALUE_BEGINS, TEST_COUNT);
    }

    @Override
    protected void tearDown() throws Exception {
        mDatabase.close();
        getContext().deleteDatabase(DATABASE_FILE);
        super.tearDown();
    }

    public void testConstructor() {
        SQLiteDirectCursorDriver cursorDriver = new SQLiteDirectCursorDriver(mDatabase,
                TEST_SQL, TABLE_NAME, null);
        try {
            new SQLiteCursor(mDatabase, cursorDriver, TABLE_NAME, null);
            fail("constructor didn't throw IllegalArgumentException when SQLiteQuery is null");
        } catch (IllegalArgumentException e) {
        }

        // get SQLiteCursor by querying database
        SQLiteCursor cursor = getCursor();
        assertNotNull(cursor);
    }

    public void testClose() {
        SQLiteCursor cursor = getCursor();
        assertTrue(cursor.moveToFirst());
        assertFalse(cursor.isClosed());
        assertTrue(cursor.requery());
        cursor.close();
        assertFalse(cursor.requery());
        try {
            cursor.moveToFirst();
            fail("moveToFirst didn't throw IllegalStateException after closed.");
        } catch (IllegalStateException e) {
        }
        assertTrue(cursor.isClosed());
    }

    public void testRegisterDataSetObserver() {
        SQLiteCursor cursor = getCursor();
        MockCursorWindow cursorWindow = new MockCursorWindow(false);

        MockObserver observer = new MockObserver();

        cursor.setWindow(cursorWindow);
        // Before registering, observer can't be notified.
        assertFalse(observer.hasInvalidated());
        cursor.moveToLast();
        assertFalse(cursorWindow.isClosed());
        cursor.deactivate();
        assertFalse(observer.hasInvalidated());
        // deactivate() will close the CursorWindow
        assertTrue(cursorWindow.isClosed());

        // test registering DataSetObserver
        assertTrue(cursor.requery());
        cursor.registerDataSetObserver(observer);
        assertFalse(observer.hasInvalidated());
        cursor.moveToLast();
        assertEquals(TEST_COUNT, cursor.getInt(1));
        cursor.deactivate();
        // deactivate method can invoke invalidate() method, can be observed by DataSetObserver.
        assertTrue(observer.hasInvalidated());

        try {
            cursor.getInt(1);
            fail("After deactivating, cursor cannot execute getting value operations.");
        } catch (StaleDataException e) {
        }

        assertTrue(cursor.requery());
        cursor.moveToLast();
        assertEquals(TEST_COUNT, cursor.getInt(1));

        // can't register a same observer twice.
        try {
            cursor.registerDataSetObserver(observer);
            fail("didn't throw IllegalStateException when register existed observer");
        } catch (IllegalStateException e) {
        }

        // after unregistering, observer can't be notified.
        cursor.unregisterDataSetObserver(observer);
        observer.resetStatus();
        assertFalse(observer.hasInvalidated());
        cursor.deactivate();
        assertFalse(observer.hasInvalidated());
    }

    public void testRequery() {
        final String DELETE = "DELETE FROM " + TABLE_NAME + " WHERE number_1 =";
        final String DELETE_1 = DELETE + "1;";
        final String DELETE_2 = DELETE + "2;";

        mDatabase.execSQL(DELETE_1);
        // when cursor is created, it refreshes CursorWindow and populates cursor count
        SQLiteCursor cursor = getCursor();
        MockObserver observer = new MockObserver();
        cursor.registerDataSetObserver(observer);
        assertEquals(TEST_COUNT - 1, cursor.getCount());
        assertFalse(observer.hasChanged());

        mDatabase.execSQL(DELETE_2);
        // when getCount() has invoked once, it can no longer refresh CursorWindow.
        assertEquals(TEST_COUNT - 1, cursor.getCount());

        assertTrue(cursor.requery());
        // only after requery, getCount can get most up-to-date counting info now.
        assertEquals(TEST_COUNT - 2, cursor.getCount());
        assertTrue(observer.hasChanged());
    }

    public void testRequery2() {
        mDatabase.disableWriteAheadLogging();
        mDatabase.execSQL("create table testRequery2 (i int);");
        mDatabase.execSQL("insert into testRequery2 values(1);");
        mDatabase.execSQL("insert into testRequery2 values(2);");
        Cursor c = mDatabase.rawQuery("select * from testRequery2 order by i", null);
        assertEquals(2, c.getCount());
        assertTrue(c.moveToFirst());
        assertEquals(1, c.getInt(0));
        assertTrue(c.moveToNext());
        assertEquals(2, c.getInt(0));
        // add more data to the table and requery
        mDatabase.execSQL("insert into testRequery2 values(3);");
        assertTrue(c.requery());
        assertEquals(3, c.getCount());
        assertTrue(c.moveToFirst());
        assertEquals(1, c.getInt(0));
        assertTrue(c.moveToNext());
        assertEquals(2, c.getInt(0));
        assertTrue(c.moveToNext());
        assertEquals(3, c.getInt(0));
        // close the database and see if requery throws an exception
        mDatabase.close();
        assertFalse(c.requery());
    }

    public void testGetColumnIndex() {
        SQLiteCursor cursor = getCursor();

        for (int i = 0; i < COLUMNS.length; i++) {
            assertEquals(i, cursor.getColumnIndex(COLUMNS[i]));
        }

        assertTrue(Arrays.equals(COLUMNS, cursor.getColumnNames()));
    }

    public void testSetSelectionArguments() {
        final String SELECTION = "_id > ?";
        int TEST_ARG1 = 2;
        int TEST_ARG2 = 5;
        SQLiteCursor cursor = (SQLiteCursor) mDatabase.query(TABLE_NAME, null, SELECTION,
                new String[] { Integer.toString(TEST_ARG1) }, null, null, null);
        assertEquals(TEST_COUNT - TEST_ARG1, cursor.getCount());
        cursor.setSelectionArguments(new String[] { Integer.toString(TEST_ARG2) });
        cursor.requery();
        assertEquals(TEST_COUNT - TEST_ARG2, cursor.getCount());
    }

    public void testRowTooBig() {
        mDatabase.execSQL("CREATE TABLE Tst (Txt BLOB NOT NULL);");
        byte[] testArr = new byte[10000];
        Arrays.fill(testArr, (byte) 1);
        for (int i = 0; i < 10; i++) {
            mDatabase.execSQL("INSERT INTO Tst VALUES (?)", new Object[]{testArr});
        }

        // Now reduce window size, so that no rows can fit
        Cursor cursor = mDatabase.rawQuery("SELECT * FROM TST", null);
        CursorWindow cw = new CursorWindow("test", 5000);
        AbstractWindowedCursor ac = (AbstractWindowedCursor) cursor;
        ac.setWindow(cw);

        try {
            ac.moveToNext();
            fail("Exception is expected when row exceeds CursorWindow size");
        } catch (SQLiteBlobTooBigException expected) {
        }
    }

    public void testFillWindowForwardOnly() {
        mDatabase.execSQL("CREATE TABLE Tst (Num Integer NOT NULL);");
        mDatabase.beginTransaction();
        for (int i = 0; i < 100; i++) {
            mDatabase.execSQL("INSERT INTO Tst VALUES (?)", new Object[]{i});
        }
        mDatabase.setTransactionSuccessful();
        mDatabase.endTransaction();
        Cursor cursor = mDatabase.rawQuery("SELECT * FROM TST", null);
        SQLiteCursor ac = (SQLiteCursor) cursor;
        CursorWindow window = new CursorWindow("test", 1000);
        ac.setFillWindowForwardOnly(true);
        ac.setWindow(window);
        assertTrue(ac.moveToFirst());
        // Now skip 70 rows and check that the window start position corresponds to row 70
        ac.move(70);
        assertEquals(70, window.getStartPosition());
    }

    public void testOnMove() {
        // Do not test this API. It is callback which:
        // 1. The callback mechanism has been tested in super class
        // 2. The functionality is implementation details, no need to test
    }

    private void createTable(String tableName, String columnNames) {
        String sql = "Create TABLE " + tableName + " (_id INTEGER PRIMARY KEY, "
                + columnNames + " );";
        mDatabase.execSQL(sql);
    }

    private void addValuesIntoTable(String tableName, int start, int end) {
        for (int i = start; i <= end; i++) {
            mDatabase.execSQL("INSERT INTO " + tableName + "(number_1) VALUES ('" + i + "');");
        }
    }

    private SQLiteCursor getCursor() {
        SQLiteCursor cursor = (SQLiteCursor) mDatabase.query(TABLE_NAME, null, null,
                null, null, null, null);
        return cursor;
    }

    private class MockObserver extends DataSetObserver {
        private boolean mHasChanged = false;
        private boolean mHasInvalidated = false;

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

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

        protected void resetStatus() {
            mHasChanged = false;
            mHasInvalidated = false;
        }

        protected boolean hasChanged() {
            return mHasChanged;
        }

        protected boolean hasInvalidated () {
            return mHasInvalidated;
        }
    }

    private class MockCursorWindow extends CursorWindow {
        private boolean mIsClosed = false;

        public MockCursorWindow(boolean localWindow) {
            super(localWindow);
        }

        @Override
        public void close() {
            super.close();
            mIsClosed = true;
        }

        public boolean isClosed() {
            return mIsClosed;
        }
    }
}
