/*
 * 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.widget.cts;

import com.android.cts.stub.R;
import com.android.common.ArrayListCursor;

import dalvik.annotation.TestLevel;
import dalvik.annotation.TestTargetClass;
import dalvik.annotation.TestTargetNew;
import dalvik.annotation.TestTargets;
import dalvik.annotation.ToBeFixed;

import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.test.InstrumentationTestCase;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
import android.widget.SimpleCursorAdapter.CursorToStringConverter;
import android.widget.SimpleCursorAdapter.ViewBinder;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;

/**
 * Test {@link SimpleCursorAdapter}.
 */
@TestTargetClass(SimpleCursorAdapter.class)
public class SimpleCursorAdapterTest extends InstrumentationTestCase {
    private static final int ADAPTER_ROW_COUNT = 20;

    private static final int DEFAULT_COLUMN_COUNT = 2;

    private static final int[] VIEWS_TO = new int[] { R.id.cursorAdapter_item0 };

    private static final String[] COLUMNS_FROM = new String[] { "column1" };

    private static final String SAMPLE_IMAGE_NAME = "testimage.jpg";

    /**
     * The simple cursor adapter. Its cursor will be set to
     * {@link SimpleCursorAdapterTest#mCursor} It will use internal
     * R.layout.simple_list_item_1.
     */
    private SimpleCursorAdapter mSimpleCursorAdapter;

    private Context mContext;

    /**
     * The original cursor and its content will be set to:
     * <TABLE>
     * <TR>
     * <TH>Column0</TH>
     * <TH>Column1</TH>
     * </TR>
     * <TR>
     * <TD>00</TD>
     * <TD>01</TD>
     * </TR>
     * <TR>
     * <TD>10</TD>
     * <TD>11</TD>
     * </TR>
     * <TR>
     * <TD>...</TD>
     * <TD>...</TD>
     * </TR>
     * <TR>
     * <TD>190</TD>
     * <TD>191</TD>
     * </TR>
     * </TABLE>
     * It has 2 columns and 20 rows
     */
    private Cursor mCursor;

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        mContext = getInstrumentation().getTargetContext();

        mCursor = createTestCursor(DEFAULT_COLUMN_COUNT, ADAPTER_ROW_COUNT);
        mSimpleCursorAdapter = new SimpleCursorAdapter(mContext, R.layout.cursoradapter_item0,
                mCursor, COLUMNS_FROM, VIEWS_TO);
    }

    @TestTargetNew(
        level = TestLevel.COMPLETE,
        method = "SimpleCursorAdapter",
        args = {android.content.Context.class, int.class, android.database.Cursor.class,
                java.lang.String[].class, int[].class}
    )
    public void testConstructor() {
        new SimpleCursorAdapter(mContext, R.layout.cursoradapter_item0,
                createTestCursor(DEFAULT_COLUMN_COUNT, ADAPTER_ROW_COUNT),
                COLUMNS_FROM, VIEWS_TO);
    }

    @TestTargetNew(
        level = TestLevel.COMPLETE,
        method = "bindView",
        args = {android.view.View.class, android.content.Context.class,
                android.database.Cursor.class}
    )
    @ToBeFixed(bug = "1417734", explanation = "should add @throws clause into javadoc of "
            + "SimpleCursorAdapter#bindView(View, Context, Cursor) if the param view is "
            + "not TextView or ImageView and ViewBinder failed to bind the view")
    public void testBindView() {
        TextView listItem = (TextView) mSimpleCursorAdapter.newView(mContext, null, null);

        listItem.setText("");
        mCursor.moveToFirst();
        mSimpleCursorAdapter.bindView(listItem, null, mCursor);
        assertEquals("01", listItem.getText().toString());

        mCursor.moveToLast();
        mSimpleCursorAdapter.bindView(listItem, null, mCursor);
        assertEquals("191", listItem.getText().toString());

        // the binder take care of binding
        listItem.setText("");
        MockViewBinder binder = new MockViewBinder(true);
        mSimpleCursorAdapter.setViewBinder(binder);
        binder.reset();
        mCursor.moveToFirst();
        mSimpleCursorAdapter.bindView(listItem, null, mCursor);
        assertTrue(binder.hasCalledSetViewValueCalledCount());
        assertEquals("", listItem.getText().toString());

        // the binder try to bind but fail
        binder = new MockViewBinder(false);
        mSimpleCursorAdapter.setViewBinder(binder);
        mCursor.moveToLast();
        mSimpleCursorAdapter.bindView(listItem, null, mCursor);
        assertTrue(binder.hasCalledSetViewValueCalledCount());
        assertEquals("191", listItem.getText().toString());

        final int [] to = { R.id.cursorAdapter_host };
        mSimpleCursorAdapter = new SimpleCursorAdapter(mContext, R.layout.cursoradapter_host,
                mCursor, COLUMNS_FROM, to);
        LinearLayout illegalView = (LinearLayout)mSimpleCursorAdapter.newView(mContext, null, null);
        try {
            // The IllegalStateException already gets thrown in the line above.
            mSimpleCursorAdapter.bindView(illegalView, null, mCursor);
            fail("Should throw IllegalStateException if the view is not TextView or ImageView");
        } catch (IllegalStateException e) {
            // expected
        }
    }

    @TestTargets({
        @TestTargetNew(
            level = TestLevel.COMPLETE,
            method = "getViewBinder",
            args = {}
        ),
        @TestTargetNew(
            level = TestLevel.COMPLETE,
            method = "setViewBinder",
            args = {ViewBinder.class}
        )
    })
    public void testAccessViewBinder() {
        assertNull(mSimpleCursorAdapter.getViewBinder());

        MockViewBinder binder = new MockViewBinder(true);
        mSimpleCursorAdapter.setViewBinder(binder);
        assertSame(binder, mSimpleCursorAdapter.getViewBinder());

        binder = new MockViewBinder(false);
        mSimpleCursorAdapter.setViewBinder(binder);
        assertSame(binder, mSimpleCursorAdapter.getViewBinder());

        mSimpleCursorAdapter.setViewBinder(null);
        assertNull(mSimpleCursorAdapter.getViewBinder());
    }

    @TestTargetNew(
        level = TestLevel.COMPLETE,
        method = "setViewText",
        args = {TextView.class, String.class}
    )
    public void testSetViewText() {
        TextView view = new TextView(mContext);
        mSimpleCursorAdapter.setViewText(view, "expected");
        assertEquals("expected", view.getText().toString());

        mSimpleCursorAdapter.setViewText(view, null);
        assertEquals("", view.getText().toString());
    }

    @TestTargetNew(
        level = TestLevel.COMPLETE,
        method = "setViewImage",
        args = {ImageView.class, String.class}
    )
    @ToBeFixed(bug = "1417734", explanation = "should add @throws clause into javadoc of "
            + "SimpleCursorAdapter#setViewImage(ImageView, String) if the param String is null")
    public void testSetViewImage() {
        // resId
        int sceneryImgResId = com.android.cts.stub.R.drawable.scenery;
        ImageView view = new ImageView(mContext);
        assertNull(view.getDrawable());
        mSimpleCursorAdapter.setViewImage(view, String.valueOf(sceneryImgResId));
        assertNotNull(view.getDrawable());
        BitmapDrawable d = (BitmapDrawable) mContext.getResources().getDrawable(
                sceneryImgResId);
        WidgetTestUtils.assertEquals(d.getBitmap(),
                ((BitmapDrawable) view.getDrawable()).getBitmap());

        // blank
        view = new ImageView(mContext);
        assertNull(view.getDrawable());
        mSimpleCursorAdapter.setViewImage(view, "");
        assertNull(view.getDrawable());

        // null
        view = new ImageView(mContext);
        assertNull(view.getDrawable());
        try {
            // Should declare NullPoinertException if the uri or value is null
            mSimpleCursorAdapter.setViewImage(view, null);
            fail("Should throw NullPointerException if the uri or value is null");
        } catch (NullPointerException e) {
            // expected
        }

        // uri
        view = new ImageView(mContext);
        assertNull(view.getDrawable());
        try {
            int testimgRawId = com.android.cts.stub.R.raw.testimage;
            mSimpleCursorAdapter.setViewImage(view,
                    createTestImage(mContext, SAMPLE_IMAGE_NAME, testimgRawId));
            assertNotNull(view.getDrawable());
            Bitmap testBitmap = WidgetTestUtils.getUnscaledBitmap(mContext.getResources(),
                    testimgRawId);
            WidgetTestUtils.assertEquals(testBitmap,
                    ((BitmapDrawable) view.getDrawable()).getBitmap());
        } finally {
            destroyTestImage(mContext, SAMPLE_IMAGE_NAME);
        }
    }

    @TestTargets({
        @TestTargetNew(
            level = TestLevel.COMPLETE,
            method = "getStringConversionColumn",
            args = {}
        ),
        @TestTargetNew(
            level = TestLevel.COMPLETE,
            method = "setStringConversionColumn",
            args = {int.class}
        )
    })
    @ToBeFixed(explanation = "SimpleCursorAdapter#setStringConversionColumn(int) "
            + "should check whether the param stringConversionColumn is out of index")
    public void testAccessStringConversionColumn() {
        // default is -1
        assertEquals(-1, mSimpleCursorAdapter.getStringConversionColumn());

        mSimpleCursorAdapter.setStringConversionColumn(1);
        assertEquals(1, mSimpleCursorAdapter.getStringConversionColumn());

        // Should check whether the column index is out of bounds
        mSimpleCursorAdapter.setStringConversionColumn(Integer.MAX_VALUE);
        assertEquals(Integer.MAX_VALUE, mSimpleCursorAdapter.getStringConversionColumn());

        // Should check whether the column index is out of bounds
        mSimpleCursorAdapter.setStringConversionColumn(Integer.MIN_VALUE);
        assertEquals(Integer.MIN_VALUE, mSimpleCursorAdapter.getStringConversionColumn());
    }

    @TestTargets({
        @TestTargetNew(
            level = TestLevel.COMPLETE,
            method = "getCursorToStringConverter",
            args = {}
        ),
        @TestTargetNew(
            level = TestLevel.COMPLETE,
            method = "setCursorToStringConverter",
            args = {CursorToStringConverter.class}
        )
    })
    public void testAccessCursorToStringConverter() {
        // default is null
        assertNull(mSimpleCursorAdapter.getCursorToStringConverter());

        CursorToStringConverter converter = new MockCursorToStringConverter();
        mSimpleCursorAdapter.setCursorToStringConverter(converter);
        assertSame(converter, mSimpleCursorAdapter.getCursorToStringConverter());

        mSimpleCursorAdapter.setCursorToStringConverter(null);
        assertNull(mSimpleCursorAdapter.getCursorToStringConverter());
    }

    @TestTargetNew(
        level = TestLevel.COMPLETE,
        notes = "Test {@link SimpleCursorAdapter#changeCursor(Cursor)}",
        method = "changeCursor",
        args = {Cursor.class}
    )
    @ToBeFixed(bug = "1417734", explanation = "should add @throws clause into javadoc of "
            + "SimpleCursorAdapter#changeCursor(Cursor) if the param cursor does not contain"
            + "any column passed in the constructor")
    public void testChangeCursor() {
        // have "column1"
        Cursor curWith3Columns = createTestCursor(3, ADAPTER_ROW_COUNT);
        mSimpleCursorAdapter.changeCursor(curWith3Columns);
        assertSame(curWith3Columns, mSimpleCursorAdapter.getCursor());

        // does not have "column1"
        Cursor curWith1Column = createTestCursor(1, ADAPTER_ROW_COUNT);
        try {
            mSimpleCursorAdapter.changeCursor(curWith1Column);
            fail("Should throw exception if the cursor does not have the "
                    + "original column passed in the constructor");
        } catch (IllegalArgumentException e) {
            // expected
        }
    }

    @TestTargetNew(
        level = TestLevel.COMPLETE,
        notes = "Test {@link SimpleCursorAdapter#convertToString(Cursor)}",
        method = "convertToString",
        args = {Cursor.class}
    )
    @ToBeFixed(bug = "1417734", explanation = "should add @throws clause into javadoc of "
            + "SimpleCursorAdapter#convertToString(Cursor) if the StringConversionColumn set "
            + "by  SimpleCursorAdapter#setStringConversionColumn(int) is beyond the columns count")
    public void testConvertToString() {
        mCursor.moveToFirst();
        assertEquals("", mSimpleCursorAdapter.convertToString(null));

        // converter is null, StringConversionColumn is set to negative
        mSimpleCursorAdapter.setStringConversionColumn(Integer.MIN_VALUE);
        assertEquals(mCursor.toString(), mSimpleCursorAdapter.convertToString(mCursor));

        // converter is null, StringConversionColumn is set to 1
        mSimpleCursorAdapter.setStringConversionColumn(1);
        assertEquals("01", mSimpleCursorAdapter.convertToString(mCursor));

        // converter is null, StringConversionColumn is set to 3 (larger than columns count)
        // the cursor has 3 columns including column0, column1 and _id which is added automatically
        mSimpleCursorAdapter.setStringConversionColumn(DEFAULT_COLUMN_COUNT + 1);
        try {
            mSimpleCursorAdapter.convertToString(mCursor);
            fail("Should throw IndexOutOfBoundsException if index is beyond the columns count");
        } catch (IndexOutOfBoundsException e) {
            // expected
        }

        Cursor curWith3Columns = createTestCursor(DEFAULT_COLUMN_COUNT + 1, ADAPTER_ROW_COUNT);
        curWith3Columns.moveToFirst();

        // converter is null, StringConversionColumn is set to 3
        // and covert with a cursor which has 4 columns
        mSimpleCursorAdapter.setStringConversionColumn(2);
        assertEquals("02", mSimpleCursorAdapter.convertToString(curWith3Columns));

        // converter is not null, StringConversionColumn is 1
        CursorToStringConverter converter = new MockCursorToStringConverter();
        mSimpleCursorAdapter.setCursorToStringConverter(converter);
        mSimpleCursorAdapter.setStringConversionColumn(1);
        ((MockCursorToStringConverter) converter).reset();
        mSimpleCursorAdapter.convertToString(curWith3Columns);
        assertTrue(((MockCursorToStringConverter) converter).hasCalledConvertToString());
    }

    @TestTargetNew(
        level = TestLevel.COMPLETE,
        method = "newView",
        args = {Context.class, Cursor.class, ViewGroup.class}
    )
    public void testNewView() {
        LayoutInflater layoutInflater = (LayoutInflater) mContext.getSystemService(
                Context.LAYOUT_INFLATER_SERVICE);
        ViewGroup viewGroup = (ViewGroup) layoutInflater.inflate(
                com.android.cts.stub.R.layout.cursoradapter_host, null);
        View result = mSimpleCursorAdapter.newView(mContext, null, viewGroup);
        assertNotNull(result);
        assertEquals(R.id.cursorAdapter_item0, result.getId());

        result = mSimpleCursorAdapter.newView(mContext, null, null);
        assertNotNull(result);
        assertEquals(R.id.cursorAdapter_item0, result.getId());
    }

    @TestTargetNew(
        level = TestLevel.COMPLETE,
        method = "newDropDownView",
        args = {Context.class, Cursor.class, ViewGroup.class}
    )
    public void testNewDropDownView() {
        LayoutInflater layoutInflater = (LayoutInflater) mContext.getSystemService(
                Context.LAYOUT_INFLATER_SERVICE);
        ViewGroup viewGroup = (ViewGroup) layoutInflater.inflate(
                com.android.cts.stub.R.layout.cursoradapter_host, null);
        View result = mSimpleCursorAdapter.newDropDownView(null, null, viewGroup);
        assertNotNull(result);
        assertEquals(R.id.cursorAdapter_item0, result.getId());
    }

    @TestTargetNew(
        level = TestLevel.COMPLETE,
        method = "changeCursorAndColumns",
        args = {Cursor.class, String[].class, int[].class}
    )
    public void testChangeCursorAndColumns() {
        assertSame(mCursor, mSimpleCursorAdapter.getCursor());

        TextView listItem = (TextView) mSimpleCursorAdapter.newView(mContext, null, null);

        mCursor.moveToFirst();
        mSimpleCursorAdapter.bindView(listItem, null, mCursor);
        assertEquals("01", listItem.getText().toString());

        mCursor.moveToLast();
        mSimpleCursorAdapter.bindView(listItem, null, mCursor);
        assertEquals("191", listItem.getText().toString());

        Cursor newCursor = createTestCursor(3, ADAPTER_ROW_COUNT);
        final String[] from = new String[] { "column2" };
        mSimpleCursorAdapter.changeCursorAndColumns(newCursor, from, VIEWS_TO);
        assertSame(newCursor, mSimpleCursorAdapter.getCursor());
        newCursor.moveToFirst();
        mSimpleCursorAdapter.bindView(listItem, null, newCursor);
        assertEquals("02", listItem.getText().toString());

        newCursor.moveToLast();
        mSimpleCursorAdapter.bindView(listItem, null, newCursor);
        assertEquals("192", listItem.getText().toString());

        mSimpleCursorAdapter.changeCursorAndColumns(null, null, null);
        assertNull(mSimpleCursorAdapter.getCursor());
    }

    /**
     * Creates the test cursor.
     *
     * @param colCount the column count
     * @param rowCount the row count
     * @return the cursor
     */
    @SuppressWarnings("unchecked")
    private Cursor createTestCursor(int colCount, int rowCount) {
        ArrayList<ArrayList> list = new ArrayList<ArrayList>();
        String[] columns = new String[colCount];
        for (int i = 0; i < colCount; i++) {
            columns[i] = "column" + i;
        }

        for (int i = 0; i < rowCount; i++) {
            ArrayList<String> row = new ArrayList<String>();
            for (int j = 0; j < colCount; j++) {
                row.add("" + i + "" + j);
            }
            list.add(row);
        }

        return new ArrayListCursor(columns, list);
    }

    private static class MockViewBinder implements ViewBinder {
        private boolean mExpectedResult;

        private boolean mHasCalledSetViewValue;

        public MockViewBinder(boolean expectedResult) {
            mExpectedResult = expectedResult;
        }

        public void reset(){
            mHasCalledSetViewValue = false;
        }

        public boolean hasCalledSetViewValueCalledCount() {
            return mHasCalledSetViewValue;
        }

        public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
            mHasCalledSetViewValue = true;
            return mExpectedResult;
        }
    }

    public static String createTestImage(Context context, String fileName, int resId) {
        InputStream source = null;
        OutputStream target = null;

        try {
            source = context.getResources().openRawResource(resId);
            target = context.openFileOutput(fileName, Context.MODE_WORLD_WRITEABLE);

            byte[] buffer = new byte[1024];
            for (int len = source.read(buffer); len > 0; len = source.read(buffer)) {
                target.write(buffer, 0, len);
            }
        } catch (IOException e) {
            fail(e.getMessage());
        } finally {
            try {
                if (source != null) {
                    source.close();
                }
                if (target != null) {
                    target.close();
                }
            } catch (IOException e) {
                // Ignore the IOException.
            }
        }

        return context.getFileStreamPath(fileName).getAbsolutePath();
    }

    public static void destroyTestImage(Context context, String fileName) {
        context.deleteFile(fileName);
    }

    private static class MockCursorToStringConverter implements CursorToStringConverter {
        private boolean mHasCalledConvertToString;

        public boolean hasCalledConvertToString() {
            return mHasCalledConvertToString;
        }

        public void reset(){
            mHasCalledConvertToString = false;
        }

        public CharSequence convertToString(Cursor cursor) {
            mHasCalledConvertToString = true;
            return null;
        }
    }
}
