/*
 * Copyright (C) 2016 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 com.android.settings.bluetooth;

import android.app.AlertDialog;
import android.content.Context;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.view.View;
import android.widget.CheckBox;
import android.widget.TextView;

import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication;
import org.robolectric.util.FragmentTestUtil;

import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class BluetoothPairingDialogTest {

    private static final String FILLER = "text that goes in a view";
    private static final String FAKE_DEVICE_NAME = "Fake Bluetooth Device";

    @Mock
    private BluetoothPairingController controller;

    @Mock
    private BluetoothPairingDialog dialogActivity;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        doNothing().when(dialogActivity).dismiss();
    }

    @Test
    public void dialogUpdatesControllerWithUserInput() {
        // set the correct dialog type
        when(controller.getDialogType()).thenReturn(BluetoothPairingController.USER_ENTRY_DIALOG);

        // we don't care about these for this test
        when(controller.getDeviceVariantMessageId())
                .thenReturn(BluetoothPairingController.INVALID_DIALOG_TYPE);
        when(controller.getDeviceVariantMessageHintId())
                .thenReturn(BluetoothPairingController.INVALID_DIALOG_TYPE);

        // build fragment
        BluetoothPairingDialogFragment frag = makeFragment();

        // test that controller is updated on text change
        frag.afterTextChanged(new SpannableStringBuilder(FILLER));
        verify(controller, times(1)).updateUserInput(any());
    }

    @Test
    public void dialogEnablesSubmitButtonOnValidationFromController() {
        // set the correct dialog type
        when(controller.getDialogType()).thenReturn(BluetoothPairingController.USER_ENTRY_DIALOG);

        // we don't care about these for this test
        when(controller.getDeviceVariantMessageId())
                .thenReturn(BluetoothPairingController.INVALID_DIALOG_TYPE);
        when(controller.getDeviceVariantMessageHintId())
                .thenReturn(BluetoothPairingController.INVALID_DIALOG_TYPE);

        // force the controller to say that any passkey is valid
        when(controller.isPasskeyValid(any())).thenReturn(true);

        // build fragment
        BluetoothPairingDialogFragment frag = makeFragment();

        // test that the positive button is enabled when passkey is valid
        frag.afterTextChanged(new SpannableStringBuilder(FILLER));
        View button = frag.getmDialog().getButton(AlertDialog.BUTTON_POSITIVE);
        assertThat(button).isNotNull();
        assertThat(button.getVisibility()).isEqualTo(View.VISIBLE);
    }

    @Test
    public void dialogDoesNotAskForPairCodeOnConsentVariant() {
        // set the dialog variant to confirmation/consent
        when(controller.getDialogType()).thenReturn(BluetoothPairingController.CONFIRMATION_DIALOG);

        // build the fragment
        BluetoothPairingDialogFragment frag = makeFragment();

        // check that the input field used by the entry dialog fragment does not exist
        View view = frag.getmDialog().findViewById(R.id.text);
        assertThat(view).isNull();
    }

    @Test
    public void dialogAsksForPairCodeOnUserEntryVariant() {
        // set the dialog variant to user entry
        when(controller.getDialogType()).thenReturn(BluetoothPairingController.USER_ENTRY_DIALOG);

        // we don't care about these for this test
        when(controller.getDeviceVariantMessageId())
                .thenReturn(BluetoothPairingController.INVALID_DIALOG_TYPE);
        when(controller.getDeviceVariantMessageHintId())
                .thenReturn(BluetoothPairingController.INVALID_DIALOG_TYPE);

        // build the fragment
        BluetoothPairingDialogFragment frag = makeFragment();

        // check that the pin/passkey input field is visible to the user
        View view = frag.getmDialog().findViewById(R.id.text);
        assertThat(view.getVisibility()).isEqualTo(View.VISIBLE);
    }

    @Test
    public void dialogDisplaysPairCodeOnDisplayPasskeyVariant() {
        // set the dialog variant to display passkey
        when(controller.getDialogType())
                .thenReturn(BluetoothPairingController.DISPLAY_PASSKEY_DIALOG);

        // ensure that the controller returns good values to indicate a passkey needs to be shown
        when(controller.isDisplayPairingKeyVariant()).thenReturn(true);
        when(controller.hasPairingContent()).thenReturn(true);
        when(controller.getPairingContent()).thenReturn(FILLER);

        // build the fragment
        BluetoothPairingDialogFragment frag = makeFragment();

        // get the relevant views
        View messagePairing = frag.getmDialog().findViewById(R.id.pairing_code_message);
        TextView pairingViewContent =
                (TextView) frag.getmDialog().findViewById(R.id.pairing_subhead);
        View pairingViewCaption = frag.getmDialog().findViewById(R.id.pairing_caption);

        // check that the relevant views are visible and that the passkey is shown
        assertThat(messagePairing.getVisibility()).isEqualTo(View.VISIBLE);
        assertThat(pairingViewCaption.getVisibility()).isEqualTo(View.VISIBLE);
        assertThat(pairingViewContent.getVisibility()).isEqualTo(View.VISIBLE);
        assertThat(TextUtils.equals(FILLER, pairingViewContent.getText())).isTrue();
    }

    @Test(expected = IllegalStateException.class)
    public void dialogThrowsExceptionIfNoControllerSet() {
        // instantiate a fragment
        BluetoothPairingDialogFragment frag = new BluetoothPairingDialogFragment();

        // this should throw an error
        FragmentTestUtil.startFragment(frag);
        fail("Starting the fragment with no controller set should have thrown an exception.");
    }

    @Test
    public void dialogCallsHookOnPositiveButtonPress() {
        // set the dialog variant to confirmation/consent
        when(controller.getDialogType()).thenReturn(BluetoothPairingController.CONFIRMATION_DIALOG);

        // we don't care what this does, just that it is called
        doNothing().when(controller).onDialogPositiveClick(any());

        // build the fragment
        BluetoothPairingDialogFragment frag = makeFragment();

        // click the button and verify that the controller hook was called
        frag.onClick(frag.getmDialog(), AlertDialog.BUTTON_POSITIVE);
        verify(controller, times(1)).onDialogPositiveClick(any());
    }

    @Test
    public void dialogCallsHookOnNegativeButtonPress() {
        // set the dialog variant to confirmation/consent
        when(controller.getDialogType()).thenReturn(BluetoothPairingController.CONFIRMATION_DIALOG);

        // we don't care what this does, just that it is called
        doNothing().when(controller).onDialogNegativeClick(any());

        // build the fragment
        BluetoothPairingDialogFragment frag = makeFragment();

        // click the button and verify that the controller hook was called
        frag.onClick(frag.getmDialog(), AlertDialog.BUTTON_NEGATIVE);
        verify(controller, times(1)).onDialogNegativeClick(any());
    }

    @Test(expected = IllegalStateException.class)
    public void dialogDoesNotAllowSwappingController() {
        // instantiate a fragment
        BluetoothPairingDialogFragment frag = new BluetoothPairingDialogFragment();
        frag.setPairingController(controller);

        // this should throw an error
        frag.setPairingController(controller);
        fail("Setting the controller multiple times should throw an exception.");
    }

    @Test(expected = IllegalStateException.class)
    public void dialogDoesNotAllowSwappingActivity() {
        // instantiate a fragment
        BluetoothPairingDialogFragment frag = new BluetoothPairingDialogFragment();
        frag.setPairingDialogActivity(dialogActivity);

        // this should throw an error
        frag.setPairingDialogActivity(dialogActivity);
        fail("Setting the dialog activity multiple times should throw an exception.");
    }

    @Test
    public void dialogPositiveButtonDisabledWhenUserInputInvalid() {
        // set the correct dialog type
        when(controller.getDialogType()).thenReturn(BluetoothPairingController.USER_ENTRY_DIALOG);

        // we don't care about these for this test
        when(controller.getDeviceVariantMessageId())
                .thenReturn(BluetoothPairingController.INVALID_DIALOG_TYPE);
        when(controller.getDeviceVariantMessageHintId())
                .thenReturn(BluetoothPairingController.INVALID_DIALOG_TYPE);

        // force the controller to say that any passkey is valid
        when(controller.isPasskeyValid(any())).thenReturn(false);

        // build fragment
        BluetoothPairingDialogFragment frag = makeFragment();

        // test that the positive button is enabled when passkey is valid
        frag.afterTextChanged(new SpannableStringBuilder(FILLER));
        View button = frag.getmDialog().getButton(AlertDialog.BUTTON_POSITIVE);
        assertThat(button).isNotNull();
        assertThat(button.isEnabled()).isFalse();
    }

    @Test
    public void dialogShowsContactSharingCheckboxWhenBluetoothProfileNotReady() {
        // set the dialog variant to confirmation/consent
        when(controller.getDialogType()).thenReturn(BluetoothPairingController.CONFIRMATION_DIALOG);

        // set a fake device name and pretend the profile has not been set up for it
        when(controller.getDeviceName()).thenReturn(FAKE_DEVICE_NAME);
        when(controller.isProfileReady()).thenReturn(false);

        // build the fragment
        BluetoothPairingDialogFragment frag = makeFragment();

        // verify that the checkbox is visible and that the device name is correct
        CheckBox sharingCheckbox = (CheckBox) frag.getmDialog()
                .findViewById(R.id.phonebook_sharing_message_confirm_pin);
        assertThat(sharingCheckbox.getVisibility()).isEqualTo(View.VISIBLE);
        assertThat(sharingCheckbox.getText().toString().contains(FAKE_DEVICE_NAME)).isTrue();
    }

    @Test
    public void dialogHidesContactSharingCheckboxWhenBluetoothProfileIsReady() {
        // set the dialog variant to confirmation/consent
        when(controller.getDialogType()).thenReturn(BluetoothPairingController.CONFIRMATION_DIALOG);

        // set a fake device name and pretend the profile has been set up for it
        when(controller.getDeviceName()).thenReturn(FAKE_DEVICE_NAME);
        when(controller.isProfileReady()).thenReturn(true);

        // build the fragment
        BluetoothPairingDialogFragment frag = makeFragment();

        // verify that the checkbox is gone
        CheckBox sharingCheckbox = (CheckBox) frag.getmDialog()
                .findViewById(R.id.phonebook_sharing_message_confirm_pin);
        assertThat(sharingCheckbox.getVisibility()).isEqualTo(View.GONE);
    }

    @Test
    public void dialogShowsMessageOnPinEntryView() {
        // set the correct dialog type
        when(controller.getDialogType()).thenReturn(BluetoothPairingController.USER_ENTRY_DIALOG);

        // Set the message id to something specific to verify later
        when(controller.getDeviceVariantMessageId()).thenReturn(R.string.cancel);
        when(controller.getDeviceVariantMessageHintId())
                .thenReturn(BluetoothPairingController.INVALID_DIALOG_TYPE);

        // build the fragment
        BluetoothPairingDialogFragment frag = makeFragment();

        // verify message is what we expect it to be and is visible
        TextView message = (TextView) frag.getmDialog().findViewById(R.id.message_below_pin);
        assertThat(message.getVisibility()).isEqualTo(View.VISIBLE);
        assertThat(TextUtils.equals(frag.getString(R.string.cancel), message.getText())).isTrue();
    }

    @Test
    public void dialogShowsMessageHintOnPinEntryView() {
        // set the correct dialog type
        when(controller.getDialogType()).thenReturn(BluetoothPairingController.USER_ENTRY_DIALOG);

        // Set the message id hint to something specific to verify later
        when(controller.getDeviceVariantMessageHintId()).thenReturn(R.string.cancel);
        when(controller.getDeviceVariantMessageId())
                .thenReturn(BluetoothPairingController.INVALID_DIALOG_TYPE);

        // build the fragment
        BluetoothPairingDialogFragment frag = makeFragment();

        // verify message is what we expect it to be and is visible
        TextView hint = (TextView) frag.getmDialog().findViewById(R.id.pin_values_hint);
        assertThat(hint.getVisibility()).isEqualTo(View.VISIBLE);
        assertThat(TextUtils.equals(frag.getString(R.string.cancel), hint.getText())).isTrue();
    }

    @Test
    public void dialogHidesMessageAndHintWhenNotProvidedOnPinEntryView() {
        // set the correct dialog type
        when(controller.getDialogType()).thenReturn(BluetoothPairingController.USER_ENTRY_DIALOG);

        // Set the id's to what is returned when it is not provided
        when(controller.getDeviceVariantMessageHintId())
                .thenReturn(BluetoothPairingController.INVALID_DIALOG_TYPE);
        when(controller.getDeviceVariantMessageId())
                .thenReturn(BluetoothPairingController.INVALID_DIALOG_TYPE);

        // build the fragment
        BluetoothPairingDialogFragment frag = makeFragment();

        // verify message is what we expect it to be and is visible
        TextView hint = (TextView) frag.getmDialog().findViewById(R.id.pin_values_hint);
        assertThat(hint.getVisibility()).isEqualTo(View.GONE);
        TextView message = (TextView) frag.getmDialog().findViewById(R.id.message_below_pin);
        assertThat(message.getVisibility()).isEqualTo(View.GONE);
    }

    @Test
    public void pairingStringIsFormattedCorrectly() {
        final String device = "test_device";
        final Context context = ShadowApplication.getInstance().getApplicationContext();
        assertThat(context.getString(R.string.bluetooth_pb_acceptance_dialog_text, device, device))
                .contains(device);
    }

    @Test
    public void pairingDialogDismissedOnPositiveClick() {
        // set the dialog variant to confirmation/consent
        when(controller.getDialogType()).thenReturn(BluetoothPairingController.CONFIRMATION_DIALOG);

        // we don't care what this does, just that it is called
        doNothing().when(controller).onDialogPositiveClick(any());

        // build the fragment
        BluetoothPairingDialogFragment frag = makeFragment();

        // click the button and verify that the controller hook was called
        frag.onClick(frag.getmDialog(), AlertDialog.BUTTON_POSITIVE);

        verify(controller, times(1)).onDialogPositiveClick(any());
        verify(dialogActivity, times(1)).dismiss();
    }

    @Test
    public void pairingDialogDismissedOnNegativeClick() {
        // set the dialog variant to confirmation/consent
        when(controller.getDialogType()).thenReturn(BluetoothPairingController.CONFIRMATION_DIALOG);

        // we don't care what this does, just that it is called
        doNothing().when(controller).onDialogNegativeClick(any());

        // build the fragment
        BluetoothPairingDialogFragment frag = makeFragment();

        // click the button and verify that the controller hook was called
        frag.onClick(frag.getmDialog(), AlertDialog.BUTTON_NEGATIVE);

        verify(controller, times(1)).onDialogNegativeClick(any());
        verify(dialogActivity, times(1)).dismiss();
    }

    private BluetoothPairingDialogFragment makeFragment() {
        BluetoothPairingDialogFragment frag = new BluetoothPairingDialogFragment();
        assertThat(frag.isPairingControllerSet()).isFalse();
        frag.setPairingController(controller);
        assertThat(frag.isPairingDialogActivitySet()).isFalse();
        frag.setPairingDialogActivity(dialogActivity);
        FragmentTestUtil.startFragment(frag);
        assertThat(frag.getmDialog()).isNotNull();
        assertThat(frag.isPairingControllerSet()).isTrue();
        assertThat(frag.isPairingDialogActivitySet()).isTrue();
        return frag;
    }
}
