/*
 * 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.systemui.privacy

import android.app.ActivityManager
import android.app.AppOpsManager
import android.content.Context
import android.content.Intent
import android.content.pm.UserInfo
import android.os.Handler
import android.os.UserHandle
import android.os.UserManager
import android.provider.DeviceConfig
import android.provider.Settings.RESET_MODE_PACKAGE_DEFAULTS
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.testing.TestableLooper.RunWithLooper
import androidx.test.filters.SmallTest
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags
import com.android.systemui.Dependency
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.appops.AppOpItem
import com.android.systemui.appops.AppOpsController
import org.hamcrest.Matchers.hasItem
import org.hamcrest.Matchers.not
import org.hamcrest.Matchers.nullValue
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertThat
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.anyList
import org.mockito.ArgumentMatchers.anyString
import org.mockito.ArgumentMatchers.eq
import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito.atLeastOnce
import org.mockito.Mockito.doAnswer
import org.mockito.Mockito.doReturn
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.reset
import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoMoreInteractions
import org.mockito.MockitoAnnotations

@RunWith(AndroidTestingRunner::class)
@SmallTest
@RunWithLooper
@Ignore
class PrivacyItemControllerTest : SysuiTestCase() {

    companion object {
        val CURRENT_USER_ID = ActivityManager.getCurrentUser()
        val TEST_UID = CURRENT_USER_ID * UserHandle.PER_USER_RANGE
        const val SYSTEM_UID = 1000
        const val TEST_PACKAGE_NAME = "test"
        const val DEVICE_SERVICES_STRING = "Device services"
        const val TAG = "PrivacyItemControllerTest"
        fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture()
    }

    @Mock
    private lateinit var appOpsController: AppOpsController
    @Mock
    private lateinit var callback: PrivacyItemController.Callback
    @Mock
    private lateinit var userManager: UserManager
    @Captor
    private lateinit var argCaptor: ArgumentCaptor<List<PrivacyItem>>
    @Captor
    private lateinit var argCaptorCallback: ArgumentCaptor<AppOpsController.Callback>

    private lateinit var testableLooper: TestableLooper
    private lateinit var privacyItemController: PrivacyItemController
    private lateinit var handler: Handler

    fun PrivacyItemController(context: Context) =
            PrivacyItemController(context, appOpsController, handler, handler)

    @Before
    fun setup() {
        MockitoAnnotations.initMocks(this)
        testableLooper = TestableLooper.get(this)
        handler = Handler(testableLooper.looper)

        appOpsController = mDependency.injectMockDependency(AppOpsController::class.java)
        mDependency.injectTestDependency(Dependency.BG_HANDLER, handler)
        mDependency.injectTestDependency(Dependency.MAIN_HANDLER, handler)
        mContext.addMockSystemService(UserManager::class.java, userManager)
        mContext.getOrCreateTestableResources().addOverride(R.string.device_services,
                DEVICE_SERVICES_STRING)
        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_PRIVACY,
                SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED,
                "true", false)

        doReturn(listOf(object : UserInfo() {
            init {
                id = CURRENT_USER_ID
            }
        })).`when`(userManager).getProfiles(anyInt())

        privacyItemController = PrivacyItemController(mContext)
    }

    @After
    fun tearDown() {
        DeviceConfig.resetToDefaults(RESET_MODE_PACKAGE_DEFAULTS, DeviceConfig.NAMESPACE_PRIVACY)
    }

    @Test
    fun testSetListeningTrueByAddingCallback() {
        privacyItemController.addCallback(callback)
        testableLooper.processAllMessages()
        verify(appOpsController).addCallback(eq(PrivacyItemController.OPS),
                any(AppOpsController.Callback::class.java))
        testableLooper.processAllMessages()
        verify(callback).privacyChanged(anyList())
    }

    @Test
    fun testSetListeningFalseByRemovingLastCallback() {
        privacyItemController.addCallback(callback)
        testableLooper.processAllMessages()
        verify(appOpsController, never()).removeCallback(any(IntArray::class.java),
                any(AppOpsController.Callback::class.java))
        privacyItemController.removeCallback(callback)
        testableLooper.processAllMessages()
        verify(appOpsController).removeCallback(eq(PrivacyItemController.OPS),
                any(AppOpsController.Callback::class.java))
        verify(callback).privacyChanged(emptyList())
    }

    @Test
    fun testDistinctItems() {
        doReturn(listOf(AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, "", 0),
                AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, "", 1)))
                .`when`(appOpsController).getActiveAppOpsForUser(anyInt())

        privacyItemController.addCallback(callback)
        testableLooper.processAllMessages()
        verify(callback).privacyChanged(capture(argCaptor))
        assertEquals(1, argCaptor.value.size)
    }

    @Test
    fun testSystemApps() {
        doReturn(listOf(AppOpItem(AppOpsManager.OP_COARSE_LOCATION, SYSTEM_UID, TEST_PACKAGE_NAME,
                0))).`when`(appOpsController).getActiveAppOpsForUser(anyInt())
        privacyItemController.addCallback(callback)
        testableLooper.processAllMessages()
        verify(callback).privacyChanged(capture(argCaptor))
        assertEquals(1, argCaptor.value.size)
        assertEquals(context.getString(R.string.device_services),
                argCaptor.value[0].application.applicationName)
    }

    @Test
    fun testRegisterReceiver_allUsers() {
        val spiedContext = spy(mContext)
        val itemController = PrivacyItemController(spiedContext)
        itemController.addCallback(callback)
        testableLooper.processAllMessages()
        verify(spiedContext, atLeastOnce()).registerReceiverAsUser(
                eq(itemController.userSwitcherReceiver), eq(UserHandle.ALL), any(), eq(null),
                eq(null))
        verify(spiedContext, never()).unregisterReceiver(eq(itemController.userSwitcherReceiver))
    }

    @Test
    fun testReceiver_ACTION_USER_FOREGROUND() {
        privacyItemController.userSwitcherReceiver.onReceive(context,
                Intent(Intent.ACTION_USER_FOREGROUND))
        verify(userManager).getProfiles(anyInt())
    }

    @Test
    fun testReceiver_ACTION_MANAGED_PROFILE_ADDED() {
        privacyItemController.userSwitcherReceiver.onReceive(context,
                Intent(Intent.ACTION_MANAGED_PROFILE_ADDED))
        verify(userManager).getProfiles(anyInt())
    }

    @Test
    fun testReceiver_ACTION_MANAGED_PROFILE_REMOVED() {
        privacyItemController.userSwitcherReceiver.onReceive(context,
                Intent(Intent.ACTION_MANAGED_PROFILE_REMOVED))
        verify(userManager).getProfiles(anyInt())
    }

    @Test
    fun testAddMultipleCallbacks() {
        val otherCallback = mock(PrivacyItemController.Callback::class.java)
        privacyItemController.addCallback(callback)
        testableLooper.processAllMessages()
        verify(callback).privacyChanged(anyList())

        privacyItemController.addCallback(otherCallback)
        testableLooper.processAllMessages()
        verify(otherCallback).privacyChanged(anyList())
        // Adding a callback should not unnecessarily call previous ones
        verifyNoMoreInteractions(callback)
    }

    @Test
    fun testMultipleCallbacksAreUpdated() {
        doReturn(emptyList<AppOpItem>()).`when`(appOpsController).getActiveAppOpsForUser(anyInt())

        val otherCallback = mock(PrivacyItemController.Callback::class.java)
        privacyItemController.addCallback(callback)
        privacyItemController.addCallback(otherCallback)
        testableLooper.processAllMessages()
        reset(callback)
        reset(otherCallback)

        verify(appOpsController).addCallback(any<IntArray>(), capture(argCaptorCallback))
        argCaptorCallback.value.onActiveStateChanged(0, TEST_UID, "", true)
        testableLooper.processAllMessages()
        verify(callback).privacyChanged(anyList())
        verify(otherCallback).privacyChanged(anyList())
    }

    @Test
    fun testRemoveCallback() {
        doReturn(emptyList<AppOpItem>()).`when`(appOpsController).getActiveAppOpsForUser(anyInt())
        val otherCallback = mock(PrivacyItemController.Callback::class.java)
        privacyItemController.addCallback(callback)
        privacyItemController.addCallback(otherCallback)
        testableLooper.processAllMessages()
        reset(callback)
        reset(otherCallback)

        verify(appOpsController).addCallback(any<IntArray>(), capture(argCaptorCallback))
        privacyItemController.removeCallback(callback)
        argCaptorCallback.value.onActiveStateChanged(0, TEST_UID, "", true)
        testableLooper.processAllMessages()
        verify(callback, never()).privacyChanged(anyList())
        verify(otherCallback).privacyChanged(anyList())
    }

    @Test
    fun testListShouldNotHaveNull() {
        doReturn(listOf(AppOpItem(AppOpsManager.OP_ACTIVATE_VPN, TEST_UID, "", 0),
                        AppOpItem(AppOpsManager.OP_COARSE_LOCATION, TEST_UID, "", 0)))
                .`when`(appOpsController).getActiveAppOpsForUser(anyInt())
        privacyItemController.addCallback(callback)
        testableLooper.processAllMessages()

        verify(callback).privacyChanged(capture(argCaptor))
        assertEquals(1, argCaptor.value.size)
        assertThat(argCaptor.value, not(hasItem(nullValue())))
    }

    @Test
    fun testListShouldBeCopy() {
        val list = listOf(PrivacyItem(PrivacyType.TYPE_CAMERA,
                PrivacyApplication("", TEST_UID, mContext)))
        privacyItemController.privacyList = list
        val privacyList = privacyItemController.privacyList
        assertEquals(list, privacyList)
        assertTrue(list !== privacyList)
    }

    @Test
    fun testNotListeningWhenIndicatorsDisabled() {
        val properties = getProperties(
                DeviceConfig.NAMESPACE_PRIVACY,
                SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED,
                false)
        privacyItemController.devicePropertiesChangedListener.onPropertiesChanged(properties)
        privacyItemController.addCallback(callback)
        testableLooper.processAllMessages()
        verify(appOpsController, never()).addCallback(eq(PrivacyItemController.OPS),
                any(AppOpsController.Callback::class.java))
    }

    private fun getProperties(namespace: String, name: String, value: Boolean):
            DeviceConfig.Properties {
        val properties = mock<DeviceConfig.Properties>(DeviceConfig.Properties::class.java)
        doReturn(namespace).`when`(properties).getNamespace()
        doReturn(setOf(name)).`when`(properties).getKeyset()
        doAnswer {
            val key: String = it.getArgument(0)
            val defaultValue: Boolean = it.getArgument(1)
            if (name.equals(key, ignoreCase = true)) {
                value
            } else {
                defaultValue
            }
        }.`when`(properties).getBoolean(anyString(), anyBoolean())
        return properties
    }
}