/*
 * Copyright 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 android.autofillservice.cts.Helper.assertFillEventForContextCommitted;
import static android.autofillservice.cts.Helper.assertFillEventForFieldsClassification;
import static android.provider.Settings.Secure.AUTOFILL_FEATURE_FIELD_CLASSIFICATION;
import static android.provider.Settings.Secure.AUTOFILL_USER_DATA_MAX_CATEGORY_COUNT;
import static android.provider.Settings.Secure.AUTOFILL_USER_DATA_MAX_FIELD_CLASSIFICATION_IDS_SIZE;
import static android.provider.Settings.Secure.AUTOFILL_USER_DATA_MAX_USER_DATA_SIZE;
import static android.provider.Settings.Secure.AUTOFILL_USER_DATA_MAX_VALUE_LENGTH;
import static android.provider.Settings.Secure.AUTOFILL_USER_DATA_MIN_VALUE_LENGTH;

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

import android.autofillservice.cts.Helper.FieldClassificationResult;
import android.autofillservice.cts.common.SettingsStateChangerRule;
import android.content.Context;
import android.platform.test.annotations.AppModeFull;
import android.service.autofill.FillEventHistory.Event;
import android.service.autofill.UserData;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
import android.widget.EditText;

import androidx.test.InstrumentationRegistry;

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

import java.util.List;

@AppModeFull // Service-specific test
public class FieldsClassificationTest extends AutoFillServiceTestCase {

    private static final Context sContext = InstrumentationRegistry.getContext();

    @ClassRule
    public static final SettingsStateChangerRule sFeatureEnabler =
            new SettingsStateChangerRule(sContext, AUTOFILL_FEATURE_FIELD_CLASSIFICATION, "1");

    @ClassRule
    public static final SettingsStateChangerRule sUserDataMaxFcSizeChanger =
            new SettingsStateChangerRule(sContext,
                    AUTOFILL_USER_DATA_MAX_FIELD_CLASSIFICATION_IDS_SIZE, "10");

    @ClassRule
    public static final SettingsStateChangerRule sUserDataMaxUserSizeChanger =
            new SettingsStateChangerRule(sContext, AUTOFILL_USER_DATA_MAX_USER_DATA_SIZE, "9");

    @ClassRule
    public static final SettingsStateChangerRule sUserDataMinValueChanger =
            new SettingsStateChangerRule(sContext, AUTOFILL_USER_DATA_MIN_VALUE_LENGTH, "5");

    @ClassRule
    public static final SettingsStateChangerRule sUserDataMaxValueChanger =
            new SettingsStateChangerRule(sContext, AUTOFILL_USER_DATA_MAX_VALUE_LENGTH, "50");

    @ClassRule
    public static final SettingsStateChangerRule sUserDataMaxCategoryChanger =
            new SettingsStateChangerRule(sContext, AUTOFILL_USER_DATA_MAX_CATEGORY_COUNT, "42");

    @Rule
    public final AutofillActivityTestRule<GridActivity> mActivityRule =
            new AutofillActivityTestRule<GridActivity>(GridActivity.class);


    private GridActivity mActivity;
    private AutofillManager mAfm;

    @Before
    public void setFixtures() {
        mActivity = mActivityRule.getActivity();
        mAfm = mActivity.getAutofillManager();
    }

    @Test
    public void testFeatureIsEnabled() throws Exception {
        enableService();
        assertThat(mAfm.isFieldClassificationEnabled()).isTrue();

        disableService();
        assertThat(mAfm.isFieldClassificationEnabled()).isFalse();
    }

    @Test
    public void testGetAlgorithm() throws Exception {
        enableService();

        // Check algorithms
        final List<String> names = mAfm.getAvailableFieldClassificationAlgorithms();
        assertThat(names.size()).isAtLeast(1);
        final String defaultAlgorithm = getDefaultAlgorithm();
        assertThat(defaultAlgorithm).isNotEmpty();
        assertThat(names).contains(defaultAlgorithm);

        // Checks invalid service
        disableService();
        assertThat(mAfm.getAvailableFieldClassificationAlgorithms()).isEmpty();
    }

    @Test
    public void testUserData() throws Exception {
        assertThat(mAfm.getUserData()).isNull();
        assertThat(mAfm.getUserDataId()).isNull();

        enableService();
        mAfm.setUserData(new UserData.Builder("user_data_id", "value", "remote_id")
                .build());
        assertThat(mAfm.getUserDataId()).isEqualTo("user_data_id");
        final UserData userData = mAfm.getUserData();
        assertThat(userData.getId()).isEqualTo("user_data_id");
        assertThat(userData.getFieldClassificationAlgorithm()).isNull();

        disableService();
        assertThat(mAfm.getUserData()).isNull();
        assertThat(mAfm.getUserDataId()).isNull();
    }

    @Test
    public void testUserDataConstraints() throws Exception {
        // NOTE: values set by the SettingsStateChangerRule @Rules should have unique values to
        // make sure the getters below are reading the right property.
        assertThat(UserData.getMaxFieldClassificationIdsSize()).isEqualTo(10);
        assertThat(UserData.getMaxUserDataSize()).isEqualTo(9);
        assertThat(UserData.getMinValueLength()).isEqualTo(5);
        assertThat(UserData.getMaxValueLength()).isEqualTo(50);
        assertThat(UserData.getMaxCategoryCount()).isEqualTo(42);
    }

    @Test
    public void testHit_oneUserData_oneDetectableField() throws Exception {
        simpleHitTest(false, null);
    }

    @Test
    public void testHit_invalidAlgorithmIsIgnored() throws Exception {
        // For simplicity's sake, let's assume that name will never be valid..
        String invalidName = " ALGORITHM, Y NO INVALID? ";

        simpleHitTest(true, invalidName);
    }

    @Test
    public void testHit_userDataAlgorithmIsReset() throws Exception {
        simpleHitTest(true, null);
    }

    private void simpleHitTest(boolean setAlgorithm, String algorithm) throws Exception {
        // Set service.
        enableService();

        // Set expectations.
        final UserData.Builder userData = new UserData.Builder("id", "FULLY", "myId");
        if (setAlgorithm) {
            userData.setFieldClassificationAlgorithm(algorithm, null);
        }
        mAfm.setUserData(userData.build());
        final MyAutofillCallback callback = mActivity.registerCallback();
        final EditText field = mActivity.getCell(1, 1);
        final AutofillId fieldId = field.getAutofillId();
        sReplier.addResponse(new CannedFillResponse.Builder()
                .setFieldClassificationIds(fieldId)
                .build());

        // Trigger autofill
        mActivity.focusCell(1, 1);
        sReplier.getNextFillRequest();

        mUiBot.assertNoDatasetsEver();
        callback.assertUiUnavailableEvent(field);

        // Simulate user input
        mActivity.setText(1, 1, "fully");

        // Finish context.
        mAfm.commit();

        // Assert results
        final List<Event> events = InstrumentedAutoFillService.getFillEvents(1);
        assertFillEventForFieldsClassification(events.get(0), fieldId, "myId", 1);
    }

    @Test
    public void testHit_manyUserData_oneDetectableField_bestMatchIsFirst() throws Exception {
        manyUserData_oneDetectableField(true);
    }

    @Test
    public void testHit_manyUserData_oneDetectableField_bestMatchIsSecond() throws Exception {
        manyUserData_oneDetectableField(false);
    }

    private void manyUserData_oneDetectableField(boolean firstMatch) throws Exception {
        // Set service.
        enableService();

        // Set expectations.
        mAfm.setUserData(new UserData.Builder("id", "Iam1ST", "1stId")
                .add("Iam2ND", "2ndId").build());
        final MyAutofillCallback callback = mActivity.registerCallback();
        final EditText field = mActivity.getCell(1, 1);
        final AutofillId fieldId = field.getAutofillId();
        sReplier.addResponse(new CannedFillResponse.Builder()
                .setFieldClassificationIds(fieldId)
                .build());

        // Trigger autofill
        mActivity.focusCell(1, 1);
        sReplier.getNextFillRequest();

        mUiBot.assertNoDatasetsEver();
        callback.assertUiUnavailableEvent(field);

        // Simulate user input
        mActivity.setText(1, 1, firstMatch ? "IAM111" : "IAM222");

        // Finish context.
        mAfm.commit();

        // Assert results
        final List<Event> events = InstrumentedAutoFillService.getFillEvents(1);
        // Best match is 0.66 (4 of 6), worst is 0.5 (3 of 6)
        if (firstMatch) {
            assertFillEventForFieldsClassification(events.get(0), new FieldClassificationResult[] {
                    new FieldClassificationResult(fieldId, new String[] { "1stId", "2ndId" },
                            new float[] { 0.66F, 0.5F })});
        } else {
            assertFillEventForFieldsClassification(events.get(0), new FieldClassificationResult[] {
                    new FieldClassificationResult(fieldId, new String[] { "2ndId", "1stId" },
                            new float[] { 0.66F, 0.5F }) });
        }
    }

    @Test
    public void testHit_oneUserData_manyDetectableFields() throws Exception {
        // Set service.
        enableService();

        // Set expectations.
        mAfm.setUserData(new UserData.Builder("id", "FULLY", "myId").build());
        final MyAutofillCallback callback = mActivity.registerCallback();
        final EditText field1 = mActivity.getCell(1, 1);
        final AutofillId fieldId1 = field1.getAutofillId();
        final EditText field2 = mActivity.getCell(1, 2);
        final AutofillId fieldId2 = field2.getAutofillId();
        sReplier.addResponse(new CannedFillResponse.Builder()
                .setFieldClassificationIds(fieldId1, fieldId2)
                .build());

        // Trigger autofill
        mActivity.focusCell(1, 1);
        sReplier.getNextFillRequest();

        mUiBot.assertNoDatasetsEver();
        callback.assertUiUnavailableEvent(field1);

        // Simulate user input
        mActivity.setText(1, 1, "fully"); // 100%
        mActivity.setText(1, 2, "fooly"); // 60%

        // Finish context.
        mAfm.commit();

        // Assert results
        final List<Event> events = InstrumentedAutoFillService.getFillEvents(1);
        assertFillEventForFieldsClassification(events.get(0),
                new FieldClassificationResult[] {
                        new FieldClassificationResult(fieldId1, "myId", 1.0F),
                        new FieldClassificationResult(fieldId2, "myId", 0.6F),
                });
    }

    @Test
    public void testHit_manyUserData_manyDetectableFields() throws Exception {
        // Set service.
        enableService();

        // Set expectations.
        mAfm.setUserData(new UserData.Builder("id", "FULLY", "myId")
                .add("ZZZZZZZZZZ", "totalMiss") // should not have matched any
                .add("EMPTY", "otherId")
                .build());
        final MyAutofillCallback callback = mActivity.registerCallback();
        final EditText field1 = mActivity.getCell(1, 1);
        final AutofillId fieldId1 = field1.getAutofillId();
        final EditText field2 = mActivity.getCell(1, 2);
        final AutofillId fieldId2 = field2.getAutofillId();
        final EditText field3 = mActivity.getCell(2, 1);
        final AutofillId fieldId3 = field3.getAutofillId();
        final EditText field4 = mActivity.getCell(2, 2);
        final AutofillId fieldId4 = field4.getAutofillId();
        sReplier.addResponse(new CannedFillResponse.Builder()
                .setFieldClassificationIds(fieldId1, fieldId2)
                .build());

        // Trigger autofill
        mActivity.focusCell(1, 1);
        sReplier.getNextFillRequest();

        mUiBot.assertNoDatasetsEver();
        callback.assertUiUnavailableEvent(field1);

        // Simulate user input
        mActivity.setText(1, 1, "fully"); // u1: 100% u2:  20%
        mActivity.setText(1, 2, "empty"); // u1:  20% u2: 100%
        mActivity.setText(2, 1, "fooly"); // u1:  60% u2:  20%
        mActivity.setText(2, 2, "emppy"); // u1:  20% u2:  80%

        // Finish context.
        mAfm.commit();

        // Assert results
        final List<Event> events = InstrumentedAutoFillService.getFillEvents(1);
        assertFillEventForFieldsClassification(events.get(0),
                new FieldClassificationResult[] {
                        new FieldClassificationResult(fieldId1, new String[] { "myId", "otherId" },
                                new float[] { 1.0F, 0.2F }),
                        new FieldClassificationResult(fieldId2, new String[] { "otherId", "myId" },
                                new float[] { 1.0F, 0.2F }),
                        new FieldClassificationResult(fieldId3, new String[] { "myId", "otherId" },
                                new float[] { 0.6F, 0.2F }),
                        new FieldClassificationResult(fieldId4, new String[] { "otherId", "myId"},
                                new float[] { 0.80F, 0.2F })});
    }

    @Test
    public void testHit_manyUserDataPerField_manyDetectableFields() throws Exception {
        // Set service.
        enableService();

        // Set expectations.
        mAfm.setUserData(new UserData.Builder("id", "zzzzz", "myId") // should not have matched any
                .add("FULL1", "myId") // match 80%, should not have been reported
                .add("FULLY", "myId") // match 100%
                .add("ZZZZZZZZZZ", "totalMiss") // should not have matched any
                .add("EMPTY", "otherId")
                .build());
        final MyAutofillCallback callback = mActivity.registerCallback();
        final EditText field1 = mActivity.getCell(1, 1);
        final AutofillId fieldId1 = field1.getAutofillId();
        final EditText field2 = mActivity.getCell(1, 2);
        final AutofillId fieldId2 = field2.getAutofillId();
        final EditText field3 = mActivity.getCell(2, 1);
        final AutofillId fieldId3 = field3.getAutofillId();
        final EditText field4 = mActivity.getCell(2, 2);
        final AutofillId fieldId4 = field4.getAutofillId();
        sReplier.addResponse(new CannedFillResponse.Builder()
                .setFieldClassificationIds(fieldId1, fieldId2)
                .build());

        // Trigger autofill
        mActivity.focusCell(1, 1);
        sReplier.getNextFillRequest();

        mUiBot.assertNoDatasetsEver();
        callback.assertUiUnavailableEvent(field1);

        // Simulate user input
        mActivity.setText(1, 1, "fully"); // u1: 100% u2:  20%
        mActivity.setText(1, 2, "empty"); // u1:  20% u2: 100%
        mActivity.setText(2, 1, "fooly"); // u1:  60% u2:  20%
        mActivity.setText(2, 2, "emppy"); // u1:  20% u2:  80%

        // Finish context.
        mAfm.commit();

        // Assert results
        final List<Event> events = InstrumentedAutoFillService.getFillEvents(1);
        assertFillEventForFieldsClassification(events.get(0),
                new FieldClassificationResult[] {
                        new FieldClassificationResult(fieldId1, new String[] { "myId", "otherId" },
                                new float[] { 1.0F, 0.2F }),
                        new FieldClassificationResult(fieldId2, new String[] { "otherId", "myId" },
                                new float[] { 1.0F, 0.2F }),
                        new FieldClassificationResult(fieldId3, new String[] { "myId", "otherId" },
                                new float[] { 0.6F, 0.2F }),
                        new FieldClassificationResult(fieldId4, new String[] { "otherId", "myId"},
                                new float[] { 0.80F, 0.2F })});
    }

    @Test
    public void testMiss() throws Exception {
        // Set service.
        enableService();

        // Set expectations.
        mAfm.setUserData(new UserData.Builder("id", "ABCDEF", "myId").build());
        final MyAutofillCallback callback = mActivity.registerCallback();
        final EditText field = mActivity.getCell(1, 1);
        final AutofillId fieldId = field.getAutofillId();
        sReplier.addResponse(new CannedFillResponse.Builder()
                .setFieldClassificationIds(fieldId)
                .build());

        // Trigger autofill
        mActivity.focusCell(1, 1);
        sReplier.getNextFillRequest();

        mUiBot.assertNoDatasetsEver();
        callback.assertUiUnavailableEvent(field);

        // Simulate user input
        mActivity.setText(1, 1, "xyz");

        // Finish context.
        mAfm.commit();

        // Assert results
        final List<Event> events = InstrumentedAutoFillService.getFillEvents(1);
        assertFillEventForContextCommitted(events.get(0));
    }

    @Test
    public void testNoUserInput() throws Exception {
        // Set service.
        enableService();

        // Set expectations.
        mAfm.setUserData(new UserData.Builder("id", "FULLY", "myId").build());
        final MyAutofillCallback callback = mActivity.registerCallback();
        final EditText field = mActivity.getCell(1, 1);
        final AutofillId fieldId = field.getAutofillId();
        sReplier.addResponse(new CannedFillResponse.Builder()
                .setFieldClassificationIds(fieldId)
                .build());

        // Trigger autofill
        mActivity.focusCell(1, 1);
        sReplier.getNextFillRequest();

        mUiBot.assertNoDatasetsEver();
        callback.assertUiUnavailableEvent(field);

        // Finish context.
        mAfm.commit();

        // Assert results
        final List<Event> events = InstrumentedAutoFillService.getFillEvents(1);
        assertFillEventForContextCommitted(events.get(0));
    }

    private String getDefaultAlgorithm() {
        return mAfm.getDefaultFieldClassificationAlgorithm();
    }

    /*
     * TODO(b/73648631): other scenarios:
     *
     * - Multipartition (for example, one response with FieldsDetection, others with datasets,
     *   saveinfo, and/or ignoredIds)
     * - make sure detectable fields don't trigger a new partition
     * v test partial hit (for example, 'fool' instead of 'full'
     * v multiple fields
     * v multiple value
     * - combinations of above items
     */
}
