package com.android.contacts.activities;

import static com.android.contacts.tests.ContactsMatchers.DataCursor.hasMimeType;
import static com.android.contacts.tests.ContactsMatchers.hasRowMatching;
import static com.android.contacts.tests.ContactsMatchers.hasValueForColumn;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.allOf;
import static org.junit.Assert.assertTrue;

import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Instrumentation;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.database.Cursor;
import android.os.Build;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Data;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.filters.SdkSuppress;
import android.support.test.filters.Suppress;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.Until;

import com.android.contacts.database.SimContactDao;
import com.android.contacts.model.AccountTypeManager;
import com.android.contacts.model.SimCard;
import com.android.contacts.model.SimContact;
import com.android.contacts.model.account.AccountWithDataSet;
import com.android.contacts.tests.AccountsTestHelper;
import com.android.contacts.tests.ContactsMatchers;
import com.android.contacts.tests.FakeSimContactDao;
import com.android.contacts.tests.StringableCursor;

import com.google.common.base.Functions;

import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

/**
 * UI Tests for {@link SimImportActivity}
 *
 * These should probably be converted to espresso tests because espresso does a better job of
 * waiting for the app to be idle once espresso library is added
 */
@MediumTest
@RunWith(AndroidJUnit4.class)
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.M)
@TargetApi(Build.VERSION_CODES.M)
public class SimImportActivityTest {

    public static final int TIMEOUT = 1000;
    private Context mContext;
    private UiDevice mDevice;
    private Instrumentation mInstrumentation;
    private FakeSimContactDao mDao;
    private AccountsTestHelper mAccountHelper;

    @Before
    public void setUp() throws Exception {
        mContext = InstrumentationRegistry.getTargetContext();
        mInstrumentation = InstrumentationRegistry.getInstrumentation();
        mDao = new FakeSimContactDao();
        SimContactDao.setFactoryForTest(Functions.<SimContactDao>constant(mDao));
        mDevice = UiDevice.getInstance(mInstrumentation);

        // Add some test accounts so that account picker is exercised
        mAccountHelper = new AccountsTestHelper();
        mAccountHelper.addTestAccount(mAccountHelper.generateAccountName("SimImportActivity1_"));
        mAccountHelper.addTestAccount(mAccountHelper.generateAccountName("SimImportActivity2_"));
        mAccountHelper.addTestAccount(mAccountHelper.generateAccountName("SimImportActivity3_"));
    }

    @After
    public void tearDown() throws Exception {
        SimContactDao.setFactoryForTest(SimContactDao.DEFAULT_FACTORY);
        mAccountHelper.cleanup();
        AccountTypeManager.setInstanceForTest(null);
    }

    @Test
    public void shouldDisplaySimContacts() {
        mDao.addSim(someSimCard(),
                        new SimContact(1, "Sim One", "5550101"),
                        new SimContact(2, "Sim Two", null),
                        new SimContact(3, null, "5550103")
                );
        mInstrumentation.startActivitySync(new Intent(mContext, SimImportActivity.class)
                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));

        mDevice.waitForIdle();

        assertTrue(mDevice.hasObject(By.text("Sim One")));
        assertTrue(mDevice.hasObject(By.text("Sim Two")));
        assertTrue(mDevice.hasObject(By.text("5550103")));
}

    @Test
    public void shouldHaveEmptyState() {
        mDao.addSim(someSimCard());

        mInstrumentation.startActivitySync(new Intent(mContext, SimImportActivity.class)
                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));

        mDevice.waitForIdle();

        assertTrue(mDevice.hasObject(By.textStartsWith("No contacts")));
    }

    @Test
    public void smokeRotateInEmptyState() {
        mDao.addSim(someSimCard());

        final Activity activity = mInstrumentation.startActivitySync(
                new Intent(mContext, SimImportActivity.class)
                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));

        assertTrue(mDevice.wait(Until.hasObject(By.textStartsWith("No contacts")), TIMEOUT));

        activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

        mDevice.waitForIdle();

        assertTrue(mDevice.hasObject(By.textStartsWith("No contacts")));
    }

    @Test
    public void smokeRotateInNonEmptyState() throws Exception {
        mDao.addSim(someSimCard(), new SimContact(1, "Name One", "5550101"),
                new SimContact(2, "Name Two", "5550102"));

        final Activity activity = mInstrumentation.startActivitySync(
                new Intent(mContext, SimImportActivity.class)
                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));

        assertTrue(mDevice.wait(Until.hasObject(By.textStartsWith("Name One")), TIMEOUT));

        activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

        mDevice.waitForIdle();

        assertTrue(mDevice.hasObject(By.textStartsWith("Name One")));
    }


    // TODO: fix this test. This doesn't work because AccountTypeManager returns a stale account
    // list (it doesn't contain the accounts added during the current test run).
    // Could use MockAccountTypeManager but probably ought to look at improving how
    // AccountTypeManager updates it's account list.
    @Suppress
    @Test
    public void selectionsAreImportedAndDisabledOnSubsequentViews() throws Exception {
        // Clear out the instance so that it will have the most recent accounts when reloaded
        AccountTypeManager.setInstanceForTest(null);

        final AccountWithDataSet targetAccount = mAccountHelper.addTestAccount(
                mAccountHelper.generateAccountName("SimImportActivity_target_"));

        mDao.addSim(someSimCard(),
                new SimContact(1, "Import One", "5550101"),
                new SimContact(2, "Skip Two", "5550102"),
                new SimContact(3, "Import Three", "5550103"),
                new SimContact(4, "Skip Four", "5550104"),
                new SimContact(5, "Skip Five", "5550105"),
                new SimContact(6, "Import Six", "5550106"));

        final Activity activity = mInstrumentation.startActivitySync(
                new Intent(mContext, SimImportActivity.class)
                        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));

        assertTrue(mDevice.wait(Until.hasObject(By.desc("Show more")), TIMEOUT));

        mDevice.findObject(By.desc("Show more")).clickAndWait(Until.newWindow(), TIMEOUT);
        mDevice.findObject(By.textStartsWith("SimImportActivity_target_")).click();
        mDevice.waitForIdle();

        mDevice.findObject(By.text("Skip Two")).click();
        mDevice.findObject(By.text("Skip Five")).click();

        assertTrue(mDevice.hasObject(By.text("Skip Two").checked(false)));
        assertTrue(mDevice.hasObject(By.text("Skip Five").checked(false)));

        activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        mDevice.wait(Until.hasObject(By.text("Import One")), TIMEOUT);
        activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER);
        mDevice.wait(Until.hasObject(By.text("Import One")), TIMEOUT);

        mDevice.findObject(By.text("IMPORT").clickable(true)).click();
        mDevice.waitForIdle();

        final Cursor cursor = new StringableCursor(
                mContext.getContentResolver().query(Data.CONTENT_URI, null,
                        ContactsContract.RawContacts.ACCOUNT_NAME + "=? AND " +
                                ContactsContract.RawContacts.ACCOUNT_TYPE+ "=?",
                        new String[] {
                                targetAccount.name,
                                targetAccount.type
                        }, null));
        // 3 contacts imported with one row for name and one for phone
        assertThat(cursor, ContactsMatchers.hasCount(3 * 2));

        assertThat(cursor, hasRowMatching(allOf(
                hasMimeType(Phone.CONTENT_ITEM_TYPE),
                hasValueForColumn(Phone.DISPLAY_NAME, "Import One"),
                hasValueForColumn(Phone.NUMBER, "5550101")
        )));
        assertThat(cursor, hasRowMatching(allOf(
                hasMimeType(Phone.CONTENT_ITEM_TYPE),
                hasValueForColumn(Phone.DISPLAY_NAME, "Import Three"),
                hasValueForColumn(Phone.NUMBER, "5550103")
        )));
        assertThat(cursor, hasRowMatching(allOf(
                hasMimeType(Phone.CONTENT_ITEM_TYPE),
                hasValueForColumn(Phone.DISPLAY_NAME, "Import Six"),
                hasValueForColumn(Phone.NUMBER, "5550106")
        )));

        cursor.close();


        mInstrumentation.startActivitySync(
                new Intent(mContext, SimImportActivity.class)
                        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));

        assertTrue(mDevice.wait(Until.hasObject(By.text("Import One")), TIMEOUT));

        mDevice.findObject(By.descStartsWith("Saving to")).clickAndWait(Until.newWindow(), TIMEOUT);
        mDevice.findObject(By.textContains(targetAccount.name)).click();
        mDevice.waitForIdle();

        assertTrue(mDevice.hasObject(By.text("Import One").checked(false).enabled(false)));
        assertTrue(mDevice.hasObject(By.text("Import Three").checked(false).enabled(false)));
        assertTrue(mDevice.hasObject(By.text("Import Six").checked(false).enabled(false)));
    }

    private SimCard someSimCard() {
        return new SimCard("id", 1, "Carrier", "SIM", "18005550101", "us");
    }

    private Matcher<SimContact> withContactId(final long id) {
        return new BaseMatcher<SimContact>() {
            @Override
            public boolean matches(Object o) {
                return (o instanceof SimContact) && ((SimContact) o).getId() == id;
            }


            @Override
            public void describeTo(Description description) {
                description.appendText("Expected SimContact with id=" + id);
            }
        };
    }
}
