/*
 * Copyright (C) 2018 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.connecteddevice.usb;

import static android.net.ConnectivityManager.TETHERING_USB;

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

import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.app.Activity;
import android.content.Context;
import android.hardware.usb.UsbManager;
import android.hardware.usb.UsbPort;
import android.net.ConnectivityManager;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;

import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.ShadowUtils;
import com.android.settings.widget.RadioButtonPreference;
import com.android.settingslib.core.lifecycle.Lifecycle;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

@RunWith(SettingsRobolectricTestRunner.class)
public class UsbDetailsFunctionsControllerTest {

    private UsbDetailsFunctionsController mDetailsFunctionsController;
    private Context mContext;
    private Lifecycle mLifecycle;
    private PreferenceCategory mPreferenceCategory;
    private PreferenceManager mPreferenceManager;
    private PreferenceScreen mScreen;
    private RadioButtonPreference mRadioButtonPreference;

    @Mock
    private UsbBackend mUsbBackend;
    @Mock
    private UsbDetailsFragment mFragment;
    @Mock
    private Activity mActivity;
    @Mock
    private ConnectivityManager mConnectivityManager;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);

        mContext = spy(RuntimeEnvironment.application);
        mLifecycle = new Lifecycle(() -> mLifecycle);
        mPreferenceManager = new PreferenceManager(mContext);
        mScreen = mPreferenceManager.createPreferenceScreen(mContext);

        when(mFragment.getActivity()).thenReturn(mActivity);
        when(mActivity.getApplicationContext()).thenReturn(mContext);
        when(mFragment.getContext()).thenReturn(mContext);
        when(mFragment.getPreferenceManager()).thenReturn(mPreferenceManager);
        when(mFragment.getPreferenceScreen()).thenReturn(mScreen);
        when(mContext.getSystemService(ConnectivityManager.class)).thenReturn(mConnectivityManager);

        mDetailsFunctionsController = new UsbDetailsFunctionsController(mContext, mFragment,
                mUsbBackend);
        mPreferenceCategory = new PreferenceCategory(mContext);
        mPreferenceCategory.setKey(mDetailsFunctionsController.getPreferenceKey());
        mScreen.addPreference(mPreferenceCategory);
        mDetailsFunctionsController.displayPreference(mScreen);

        mRadioButtonPreference = new RadioButtonPreference(mContext);
    }

    @Test
    public void displayRefresh_allAllowed_shouldCreatePrefs() {
        when(mUsbBackend.areFunctionsSupported(anyLong())).thenReturn(true);

        mDetailsFunctionsController.displayPreference(mScreen);
        mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_NONE, UsbPort.POWER_ROLE_SINK,
                UsbPort.DATA_ROLE_DEVICE);
        List<RadioButtonPreference> prefs = getRadioPreferences();
        Iterator<Long> iter = UsbDetailsFunctionsController.FUNCTIONS_MAP.keySet().iterator();

        for (RadioButtonPreference pref : prefs) {
            assertThat(pref.getKey()).isEqualTo(UsbBackend.usbFunctionsToString(iter.next()));
        }
    }

    @Test
    public void displayRefresh_disconnected_shouldDisable() {
        when(mUsbBackend.areFunctionsSupported(anyLong())).thenReturn(true);

        mDetailsFunctionsController.refresh(false, UsbManager.FUNCTION_NONE,
                UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE);
        assertThat(mPreferenceCategory.isEnabled()).isFalse();
    }

    @Test
    public void displayRefresh_onlyMidiAllowed_shouldCreateOnlyMidiPref() {
        when(mUsbBackend.areFunctionsSupported(UsbManager.FUNCTION_MIDI)).thenReturn(true);
        when(mUsbBackend.areFunctionsSupported(UsbManager.FUNCTION_MTP)).thenReturn(false);
        when(mUsbBackend.areFunctionsSupported(UsbManager.FUNCTION_PTP)).thenReturn(false);
        when(mUsbBackend.areFunctionsSupported(UsbManager.FUNCTION_RNDIS)).thenReturn(false);

        mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_NONE, UsbPort.POWER_ROLE_SINK,
                UsbPort.DATA_ROLE_DEVICE);
        List<RadioButtonPreference> prefs = getRadioPreferences();
        assertThat(prefs.size()).isEqualTo(1);
        assertThat(prefs.get(0).getKey())
                .isEqualTo(UsbBackend.usbFunctionsToString(UsbManager.FUNCTION_MIDI));
    }

    @Test
    public void displayRefresh_mtpEnabled_shouldCheckSwitches() {
        when(mUsbBackend.areFunctionsSupported(anyLong())).thenReturn(true);

        mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_MTP, UsbPort.POWER_ROLE_SINK,
                UsbPort.DATA_ROLE_DEVICE);
        List<RadioButtonPreference> prefs = getRadioPreferences();

        assertThat(prefs.get(0).getKey())
                .isEqualTo(UsbBackend.usbFunctionsToString(UsbManager.FUNCTION_MTP));
        assertThat(prefs.get(0).isChecked()).isTrue();
    }

    @Test
    public void onClickMtp_noneEnabled_shouldEnableMtp() {
        when(mUsbBackend.areFunctionsSupported(anyLong())).thenReturn(true);

        mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_NONE, UsbPort.POWER_ROLE_SINK,
                UsbPort.DATA_ROLE_DEVICE);
        when(mUsbBackend.getCurrentFunctions()).thenReturn(UsbManager.FUNCTION_NONE);
        List<RadioButtonPreference> prefs = getRadioPreferences();
        prefs.get(0).performClick();

        assertThat(prefs.get(0).getKey())
                .isEqualTo(UsbBackend.usbFunctionsToString(UsbManager.FUNCTION_MTP));
        verify(mUsbBackend).setCurrentFunctions(UsbManager.FUNCTION_MTP);
        mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_MTP, UsbPort.POWER_ROLE_SINK,
                UsbPort.DATA_ROLE_DEVICE);
        assertThat(prefs.get(0).isChecked()).isTrue();
    }

    @Test
    public void onClickMtp_ptpEnabled_shouldEnableMtp() {
        when(mUsbBackend.areFunctionsSupported(anyLong())).thenReturn(true);

        mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_PTP, UsbPort.POWER_ROLE_SINK,
                UsbPort.DATA_ROLE_DEVICE);
        when(mUsbBackend.getCurrentFunctions()).thenReturn(UsbManager.FUNCTION_PTP);
        List<RadioButtonPreference> prefs = getRadioPreferences();
        prefs.get(0).performClick();

        assertThat(prefs.get(0).getKey())
                .isEqualTo(UsbBackend.usbFunctionsToString(UsbManager.FUNCTION_MTP));
        verify(mUsbBackend).setCurrentFunctions(UsbManager.FUNCTION_MTP);
        mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_MTP, UsbPort.POWER_ROLE_SINK,
                UsbPort.DATA_ROLE_DEVICE);
        assertThat(prefs.get(0).isChecked()).isTrue();
        assertThat(prefs.get(3).getKey())
                .isEqualTo(UsbBackend.usbFunctionsToString(UsbManager.FUNCTION_PTP));
        assertThat(prefs.get(3).isChecked()).isFalse();
    }

    @Test
    public void onClickNone_mtpEnabled_shouldDisableMtp() {
        when(mUsbBackend.areFunctionsSupported(anyLong())).thenReturn(true);

        mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_MTP, UsbPort.POWER_ROLE_SINK,
                UsbPort.DATA_ROLE_DEVICE);
        when(mUsbBackend.getCurrentFunctions()).thenReturn(UsbManager.FUNCTION_MTP);
        List<RadioButtonPreference> prefs = getRadioPreferences();
        prefs.get(4).performClick();

        assertThat(prefs.get(4).getKey())
                .isEqualTo(UsbBackend.usbFunctionsToString(UsbManager.FUNCTION_NONE));
        verify(mUsbBackend).setCurrentFunctions(UsbManager.FUNCTION_NONE);
        mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_NONE, UsbPort.POWER_ROLE_SINK,
                UsbPort.DATA_ROLE_DEVICE);
        assertThat(prefs.get(0).isChecked()).isFalse();
    }

    @Test
    @Config(shadows = ShadowUtils.class)
    public void isAvailable_isMonkey_shouldReturnFalse() {
        ShadowUtils.setIsUserAMonkey(true);
        assertThat(mDetailsFunctionsController.isAvailable()).isFalse();
    }

    private List<RadioButtonPreference> getRadioPreferences() {
        ArrayList<RadioButtonPreference> result = new ArrayList<>();
        for (int i = 0; i < mPreferenceCategory.getPreferenceCount(); i++) {
            result.add((RadioButtonPreference) mPreferenceCategory.getPreference(i));
        }
        return result;
    }

    @Test
    public void onRadioButtonClicked_functionRndis_startTetheringInvoked() {
        mRadioButtonPreference.setKey(UsbBackend.usbFunctionsToString(UsbManager.FUNCTION_RNDIS));
        doReturn(UsbManager.FUNCTION_MTP).when(mUsbBackend).getCurrentFunctions();

        mDetailsFunctionsController.onRadioButtonClicked(mRadioButtonPreference);

        verify(mConnectivityManager).startTethering(TETHERING_USB, true,
                mDetailsFunctionsController.mOnStartTetheringCallback);
        assertThat(mDetailsFunctionsController.mPreviousFunction).isEqualTo(
                UsbManager.FUNCTION_MTP);
    }

    @Test
    public void onRadioButtonClicked_functionOther_setCurrentFunctionInvoked() {
        mRadioButtonPreference.setKey(UsbBackend.usbFunctionsToString(UsbManager.FUNCTION_PTP));
        doReturn(UsbManager.FUNCTION_MTP).when(mUsbBackend).getCurrentFunctions();

        mDetailsFunctionsController.onRadioButtonClicked(mRadioButtonPreference);

        verify(mUsbBackend).setCurrentFunctions(UsbManager.FUNCTION_PTP);
        assertThat(mDetailsFunctionsController.mPreviousFunction).isEqualTo(
                UsbManager.FUNCTION_MTP);
    }

    @Test
    public void onRadioButtonClicked_clickSameButton_doNothing() {
        mRadioButtonPreference.setKey(UsbBackend.usbFunctionsToString(UsbManager.FUNCTION_PTP));
        doReturn(UsbManager.FUNCTION_PTP).when(mUsbBackend).getCurrentFunctions();

        mDetailsFunctionsController.onRadioButtonClicked(mRadioButtonPreference);

        verify(mUsbBackend, never()).setCurrentFunctions(UsbManager.FUNCTION_PTP);
        verify(mConnectivityManager, never()).startTethering(TETHERING_USB, true,
                mDetailsFunctionsController.mOnStartTetheringCallback);
    }

    @Test
    public void onTetheringFailed_resetPreviousFunctions() {
        mDetailsFunctionsController.mPreviousFunction = UsbManager.FUNCTION_PTP;

        mDetailsFunctionsController.mOnStartTetheringCallback.onTetheringFailed();

        verify(mUsbBackend).setCurrentFunctions(UsbManager.FUNCTION_PTP);
    }
}
