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

import static com.google.common.truth.Truth.assertThat;

import static org.testng.Assert.assertThrows;

import android.icu.util.Calendar;
import android.platform.test.annotations.AppModeFull;
import android.view.View;
import android.view.autofill.AutofillValue;
import android.widget.CompoundButton;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Spinner;
import android.widget.TimePicker;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;

/*
 * TODO: refactor this class.
 *
 * It has 2 types of tests:
 *  1. unit tests that asserts AutofillValue methods
 *  2. integrationg tests that uses a the InstrumentedAutofillService
 *
 *  The unit tests (createXxxx*() should either be moved to the CtsViewTestCases module or to a
 *  class that does not need to extend AutoFillServiceTestCase.
 *
 *  Most integration tests overlap the tests on CheckoutActivityTest - we should remove the
 *  redundant tests and add more tests (like triggering autofill using different views) to
 *  CheckoutActivityTest.
 */
@AppModeFull // Unit test
public class AutofillValueTest extends AutoFillServiceTestCase {
    @Rule
    public final AutofillActivityTestRule<AllAutofillableViewsActivity> mActivityRule =
            new AutofillActivityTestRule<>(AllAutofillableViewsActivity.class);

    private AllAutofillableViewsActivity mActivity;
    private EditText mEditText;
    private CompoundButton mCompoundButton;
    private RadioGroup mRadioGroup;
    private RadioButton mRadioButton1;
    private RadioButton mRadioButton2;
    private Spinner mSpinner;
    private DatePicker mDatePicker;
    private TimePicker mTimePicker;

    @Before
    public void setFields() {
        mActivity = mActivityRule.getActivity();

        mEditText = (EditText) mActivity.findViewById(R.id.editText);
        mCompoundButton = (CompoundButton) mActivity.findViewById(R.id.compoundButton);
        mRadioGroup = (RadioGroup) mActivity.findViewById(R.id.radioGroup);
        mRadioButton1 = (RadioButton) mActivity.findViewById(R.id.radioButton1);
        mRadioButton2 = (RadioButton) mActivity.findViewById(R.id.radioButton2);
        mSpinner = (Spinner) mActivity.findViewById(R.id.spinner);
        mDatePicker = (DatePicker) mActivity.findViewById(R.id.datePicker);
        mTimePicker = (TimePicker) mActivity.findViewById(R.id.timePicker);
    }

    @Test
    public void createTextValue() throws Exception {
        assertThat(AutofillValue.forText(null)).isNull();

        assertThat(AutofillValue.forText("").isText()).isTrue();
        assertThat(AutofillValue.forText("").isToggle()).isFalse();
        assertThat(AutofillValue.forText("").isList()).isFalse();
        assertThat(AutofillValue.forText("").isDate()).isFalse();

        AutofillValue emptyV = AutofillValue.forText("");
        assertThat(emptyV.getTextValue().toString()).isEqualTo("");

        final AutofillValue v = AutofillValue.forText("someText");
        assertThat(v.getTextValue()).isEqualTo("someText");

        assertThrows(IllegalStateException.class, v::getToggleValue);
        assertThrows(IllegalStateException.class, v::getListValue);
        assertThrows(IllegalStateException.class, v::getDateValue);
    }

    @Test
    public void createToggleValue() throws Exception {
        assertThat(AutofillValue.forToggle(true).getToggleValue()).isTrue();
        assertThat(AutofillValue.forToggle(false).getToggleValue()).isFalse();

        assertThat(AutofillValue.forToggle(true).isText()).isFalse();
        assertThat(AutofillValue.forToggle(true).isToggle()).isTrue();
        assertThat(AutofillValue.forToggle(true).isList()).isFalse();
        assertThat(AutofillValue.forToggle(true).isDate()).isFalse();


        final AutofillValue v = AutofillValue.forToggle(true);

        assertThrows(IllegalStateException.class, v::getTextValue);
        assertThrows(IllegalStateException.class, v::getListValue);
        assertThrows(IllegalStateException.class, v::getDateValue);
    }

    @Test
    public void createListValue() throws Exception {
        assertThat(AutofillValue.forList(-1).getListValue()).isEqualTo(-1);
        assertThat(AutofillValue.forList(0).getListValue()).isEqualTo(0);
        assertThat(AutofillValue.forList(1).getListValue()).isEqualTo(1);

        assertThat(AutofillValue.forList(0).isText()).isFalse();
        assertThat(AutofillValue.forList(0).isToggle()).isFalse();
        assertThat(AutofillValue.forList(0).isList()).isTrue();
        assertThat(AutofillValue.forList(0).isDate()).isFalse();

        final AutofillValue v = AutofillValue.forList(0);

        assertThrows(IllegalStateException.class, v::getTextValue);
        assertThrows(IllegalStateException.class, v::getToggleValue);
        assertThrows(IllegalStateException.class, v::getDateValue);
    }

    @Test
    public void createDateValue() throws Exception {
        assertThat(AutofillValue.forDate(-1).getDateValue()).isEqualTo(-1);
        assertThat(AutofillValue.forDate(0).getDateValue()).isEqualTo(0);
        assertThat(AutofillValue.forDate(1).getDateValue()).isEqualTo(1);

        assertThat(AutofillValue.forDate(0).isText()).isFalse();
        assertThat(AutofillValue.forDate(0).isToggle()).isFalse();
        assertThat(AutofillValue.forDate(0).isList()).isFalse();
        assertThat(AutofillValue.forDate(0).isDate()).isTrue();

        final AutofillValue v = AutofillValue.forDate(0);

        assertThrows(IllegalStateException.class, v::getTextValue);
        assertThrows(IllegalStateException.class, v::getToggleValue);
        assertThrows(IllegalStateException.class, v::getListValue);
    }

    /**
     * Trigger autofill on a view.
     *
     * @param view The view to trigger the autofill on
     */
    private void startAutoFill(@NonNull View view) throws Exception {
        mActivity.syncRunOnUiThread(() -> {
            view.clearFocus();
            view.requestFocus();
        });

        sReplier.getNextFillRequest();
    }

    private void autofillEditText(@Nullable AutofillValue value, String expectedText,
            boolean expectAutoFill) throws Exception {
        mActivity.syncRunOnUiThread(() -> mEditText.setVisibility(View.VISIBLE));

        // Set service.
        enableService();

        // Set expectations.
        sReplier.addResponse(new CannedFillResponse.CannedDataset.Builder()
                .setField("editText", value)
                .setPresentation(createPresentation("dataset"))
                .build());
        OneTimeTextWatcher textWatcher = new OneTimeTextWatcher("editText", mEditText,
                expectedText);
        mEditText.addTextChangedListener(textWatcher);

        // Trigger autofill.
        startAutoFill(mEditText);

        // Autofill it.
        mUiBot.selectDataset("dataset");

        if (expectAutoFill) {
            // Check the results.
            textWatcher.assertAutoFilled();
        } else {
            assertThat(mEditText.getText().toString()).isEqualTo(expectedText);
        }
    }

    @Test
    public void autofillValidTextValue() throws Exception {
        autofillEditText(AutofillValue.forText("filled"), "filled", true);
    }

    @Test
    public void autofillEmptyTextValue() throws Exception {
        autofillEditText(AutofillValue.forText(""), "", true);
    }

    @Test
    public void autofillTextWithListValue() throws Exception {
        autofillEditText(AutofillValue.forList(0), "", false);
    }

    @Test
    public void getEditTextAutoFillValue() throws Exception {
        mActivity.syncRunOnUiThread(() -> mEditText.setText("test"));
        assertThat(mEditText.getAutofillValue()).isEqualTo(AutofillValue.forText("test"));

        mActivity.syncRunOnUiThread(() -> mEditText.setEnabled(false));
        assertThat(mEditText.getAutofillValue()).isNull();
    }

    private void autofillCompoundButton(@Nullable AutofillValue value, boolean expectedValue,
            boolean expectAutoFill) throws Exception {
        mActivity.syncRunOnUiThread(() -> mCompoundButton.setVisibility(View.VISIBLE));

        // Set service.
        enableService();

        // Set expectations.
        sReplier.addResponse(new CannedFillResponse.CannedDataset.Builder()
                .setField("compoundButton", value)
                .setPresentation(createPresentation("dataset"))
                .build());
        OneTimeCompoundButtonListener checkedWatcher = new OneTimeCompoundButtonListener(
                    "compoundButton", mCompoundButton, expectedValue);
        mCompoundButton.setOnCheckedChangeListener(checkedWatcher);

        startAutoFill(mCompoundButton);

        // Autofill it.
        mUiBot.selectDataset("dataset");

        if (expectAutoFill) {
            // Check the results.
            checkedWatcher.assertAutoFilled();
        } else {
            assertThat(mCompoundButton.isChecked()).isEqualTo(expectedValue);
        }
    }

    @Test
    public void autofillToggleValueWithTrue() throws Exception {
        autofillCompoundButton(AutofillValue.forToggle(true), true, true);
    }

    @Test
    public void autofillToggleValueWithFalse() throws Exception {
        autofillCompoundButton(AutofillValue.forToggle(false), false, false);
    }

    @Test
    public void autofillCompoundButtonWithTextValue() throws Exception {
        autofillCompoundButton(AutofillValue.forText(""), false, false);
    }

    @Test
    public void getCompoundButtonAutoFillValue() throws Exception {
        mActivity.syncRunOnUiThread(() -> mCompoundButton.setChecked(true));
        assertThat(mCompoundButton.getAutofillValue()).isEqualTo(AutofillValue.forToggle(true));

        mActivity.syncRunOnUiThread(() -> mCompoundButton.setEnabled(false));
        assertThat(mCompoundButton.getAutofillValue()).isNull();
    }

    private void autofillListValue(@Nullable AutofillValue value, int expectedValue,
            boolean expectAutoFill) throws Exception {
        mActivity.syncRunOnUiThread(() -> mSpinner.setVisibility(View.VISIBLE));

        // Set service.
        enableService();

        // Set expectations.
        sReplier.addResponse(new CannedFillResponse.CannedDataset.Builder()
                .setField("spinner", value)
                .setPresentation(createPresentation("dataset"))
                .build());
        OneTimeSpinnerListener spinnerWatcher = new OneTimeSpinnerListener(
                "spinner", mSpinner, expectedValue);
        mSpinner.setOnItemSelectedListener(spinnerWatcher);

        startAutoFill(mSpinner);

        // Autofill it.
        mUiBot.selectDataset("dataset");

        if (expectAutoFill) {
            // Check the results.
            spinnerWatcher.assertAutoFilled();
        } else {
            assertThat(mSpinner.getSelectedItemPosition()).isEqualTo(expectedValue);
        }
    }

    @Test
    public void autofillZeroListValueToSpinner() throws Exception {
        autofillListValue(AutofillValue.forList(0), 0, false);
    }

    @Test
    public void autofillOneListValueToSpinner() throws Exception {
        autofillListValue(AutofillValue.forList(1), 1, true);
    }

    @Test
    public void autofillInvalidListValueToSpinner() throws Exception {
        autofillListValue(AutofillValue.forList(-1), 0, false);
    }

    @Test
    public void autofillSpinnerWithTextValue() throws Exception {
        autofillListValue(AutofillValue.forText(""), 0, false);
    }

    @Test
    public void getSpinnerAutoFillValue() throws Exception {
        mActivity.syncRunOnUiThread(() -> mSpinner.setSelection(1));
        assertThat(mSpinner.getAutofillValue()).isEqualTo(AutofillValue.forList(1));

        mActivity.syncRunOnUiThread(() -> mSpinner.setEnabled(false));
        assertThat(mSpinner.getAutofillValue()).isNull();
    }

    private void autofillDateValueToDatePicker(@Nullable AutofillValue value,
            boolean expectAutoFill) throws Exception {
        mActivity.syncRunOnUiThread(() -> {
            mEditText.setVisibility(View.VISIBLE);
            mDatePicker.setVisibility(View.VISIBLE);
        });

        // Set service.
        enableService();

        // Set expectations.
        sReplier.addResponse(new CannedFillResponse.CannedDataset.Builder()
                .setField("datePicker", value)
                .setField("editText", "filled")
                .setPresentation(createPresentation("dataset"))
                .build());
        OneTimeDateListener dateWatcher = new OneTimeDateListener("datePicker", mDatePicker,
                2017, 3, 7);
        mDatePicker.setOnDateChangedListener(dateWatcher);

        int nonAutofilledYear = mDatePicker.getYear();
        int nonAutofilledMonth = mDatePicker.getMonth();
        int nonAutofilledDay = mDatePicker.getDayOfMonth();

        // Trigger autofill.
        startAutoFill(mEditText);

        // Autofill it.
        mUiBot.selectDataset("dataset");

        if (expectAutoFill) {
            // Check the results.
            dateWatcher.assertAutoFilled();
        } else {
            Helper.assertDateValue(mDatePicker, nonAutofilledYear, nonAutofilledMonth,
                    nonAutofilledDay);
        }
    }

    private long getDateAsMillis(int year, int month, int day, int hour, int minute) {
        Calendar calendar = Calendar.getInstance(
                mActivity.getResources().getConfiguration().getLocales().get(0));

        calendar.set(year, month, day, hour, minute);

        return calendar.getTimeInMillis();
    }

    @Test
    public void autofillValidDateValueToDatePicker() throws Exception {
        autofillDateValueToDatePicker(AutofillValue.forDate(getDateAsMillis(2017, 3, 7, 12, 32)),
                true);
    }

    @Test
    public void autofillDatePickerWithTextValue() throws Exception {
        autofillDateValueToDatePicker(AutofillValue.forText(""), false);
    }

    @Test
    public void getDatePickerAutoFillValue() throws Exception {
        mActivity.syncRunOnUiThread(() -> mDatePicker.updateDate(2017, 3, 7));

        Helper.assertDateValue(mDatePicker, 2017, 3, 7);

        mActivity.syncRunOnUiThread(() -> mDatePicker.setEnabled(false));
        assertThat(mDatePicker.getAutofillValue()).isNull();
    }

    private void autofillDateValueToTimePicker(@Nullable AutofillValue value,
            boolean expectAutoFill) throws Exception {
        mActivity.syncRunOnUiThread(() -> {
            mEditText.setVisibility(View.VISIBLE);
            mTimePicker.setIs24HourView(true);
            mTimePicker.setVisibility(View.VISIBLE);
        });

        // Set service.
        enableService();

        // Set expectations.
        sReplier.addResponse(new CannedFillResponse.CannedDataset.Builder()
                .setField("timePicker", value)
                .setField("editText", "filled")
                .setPresentation(createPresentation("dataset"))
                .build());
        MultipleTimesTimeListener timeWatcher = new MultipleTimesTimeListener("timePicker", 1,
                mTimePicker, 12, 32);
        mTimePicker.setOnTimeChangedListener(timeWatcher);

        int nonAutofilledHour = mTimePicker.getHour();
        int nonAutofilledMinute = mTimePicker.getMinute();

        // Trigger autofill.
        startAutoFill(mEditText);

        // Autofill it.
        mUiBot.selectDataset("dataset");

        if (expectAutoFill) {
            // Check the results.
            timeWatcher.assertAutoFilled();
        } else {
            Helper.assertTimeValue(mTimePicker, nonAutofilledHour, nonAutofilledMinute);
        }
    }

    @Test
    public void autofillValidDateValueToTimePicker() throws Exception {
        autofillDateValueToTimePicker(AutofillValue.forDate(getDateAsMillis(2017, 3, 7, 12, 32)),
                true);
    }

    @Test
    public void autofillTimePickerWithTextValue() throws Exception {
        autofillDateValueToTimePicker(AutofillValue.forText(""), false);
    }

    @Test
    public void getTimePickerAutoFillValue() throws Exception {
        mActivity.syncRunOnUiThread(() -> {
            mTimePicker.setHour(12);
            mTimePicker.setMinute(32);
        });

        Helper.assertTimeValue(mTimePicker, 12, 32);

        mActivity.syncRunOnUiThread(() -> mTimePicker.setEnabled(false));
        assertThat(mTimePicker.getAutofillValue()).isNull();
    }

    private void autofillRadioGroup(@Nullable AutofillValue value, int expectedValue,
            boolean expectAutoFill) throws Exception {
        mActivity.syncRunOnUiThread(() -> mEditText.setVisibility(View.VISIBLE));
        mActivity.syncRunOnUiThread(() -> mRadioGroup.setVisibility(View.VISIBLE));

        // Set service.
        enableService();

        // Set expectations.
        sReplier.addResponse(new CannedFillResponse.CannedDataset.Builder()
                .setField("radioGroup", value)
                .setField("editText", "filled")
                .setPresentation(createPresentation("dataset"))
                .build());
        MultipleTimesRadioGroupListener radioGroupWatcher = new MultipleTimesRadioGroupListener(
                "radioGroup", 2, mRadioGroup, expectedValue);
        mRadioGroup.setOnCheckedChangeListener(radioGroupWatcher);

        // Trigger autofill.
        startAutoFill(mEditText);

        // Autofill it.
        mUiBot.selectDataset("dataset");

        if (expectAutoFill) {
            // Check the results.
            radioGroupWatcher.assertAutoFilled();
        } else {
            if (expectedValue == 0) {
                assertThat(mRadioButton1.isChecked()).isEqualTo(true);
                assertThat(mRadioButton2.isChecked()).isEqualTo(false);
            } else {
                assertThat(mRadioButton1.isChecked()).isEqualTo(false);
                assertThat(mRadioButton2.isChecked()).isEqualTo(true);

            }
        }
    }

    @Test
    public void autofillZeroListValueToRadioGroup() throws Exception {
        autofillRadioGroup(AutofillValue.forList(0), 0, false);
    }

    @Test
    public void autofillOneListValueToRadioGroup() throws Exception {
        autofillRadioGroup(AutofillValue.forList(1), 1, true);
    }

    @Test
    public void autofillInvalidListValueToRadioGroup() throws Exception {
        autofillListValue(AutofillValue.forList(-1), 0, false);
    }

    @Test
    public void autofillRadioGroupWithTextValue() throws Exception {
        autofillRadioGroup(AutofillValue.forText(""), 0, false);
    }

    @Test
    public void getRadioGroupAutoFillValue() throws Exception {
        mActivity.syncRunOnUiThread(() -> mRadioButton2.setChecked(true));
        assertThat(mRadioGroup.getAutofillValue()).isEqualTo(AutofillValue.forList(1));

        mActivity.syncRunOnUiThread(() -> mRadioGroup.setEnabled(false));
        assertThat(mRadioGroup.getAutofillValue()).isNull();
    }
}
