/*
 * Copyright (C) 2019 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.controls.controller

import android.app.ActivityManager
import android.app.PendingIntent
import android.app.backup.BackupManager
import android.content.BroadcastReceiver
import android.content.ComponentName
import android.content.ContentResolver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.database.ContentObserver
import android.net.Uri
import android.os.Environment
import android.os.UserHandle
import android.provider.Settings
import android.service.controls.Control
import android.service.controls.actions.ControlAction
import android.util.ArrayMap
import android.util.Log
import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.Dumpable
import com.android.systemui.backup.BackupHelper
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.controls.ControlStatus
import com.android.systemui.controls.ControlsServiceInfo
import com.android.systemui.controls.management.ControlsListingController
import com.android.systemui.controls.ui.ControlsUiController
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dump.DumpManager
import com.android.systemui.util.concurrency.DelayableExecutor
import java.io.FileDescriptor
import java.io.PrintWriter
import java.util.Optional
import java.util.concurrent.TimeUnit
import java.util.function.Consumer
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class ControlsControllerImpl @Inject constructor (
    private val context: Context,
    @Background private val executor: DelayableExecutor,
    private val uiController: ControlsUiController,
    private val bindingController: ControlsBindingController,
    private val listingController: ControlsListingController,
    private val broadcastDispatcher: BroadcastDispatcher,
    optionalWrapper: Optional<ControlsFavoritePersistenceWrapper>,
    dumpManager: DumpManager
) : Dumpable, ControlsController {

    companion object {
        private const val TAG = "ControlsControllerImpl"
        internal const val CONTROLS_AVAILABLE = Settings.Secure.CONTROLS_ENABLED
        internal val URI = Settings.Secure.getUriFor(CONTROLS_AVAILABLE)
        private const val USER_CHANGE_RETRY_DELAY = 500L // ms
        private const val DEFAULT_ENABLED = 1
        private const val PERMISSION_SELF = "com.android.systemui.permission.SELF"
    }

    private var userChanging: Boolean = true

    private var loadCanceller: Runnable? = null

    private var seedingInProgress = false
    private val seedingCallbacks = mutableListOf<Consumer<Boolean>>()

    private var currentUser = UserHandle.of(ActivityManager.getCurrentUser())
    override val currentUserId
        get() = currentUser.identifier

    private val contentResolver: ContentResolver
        get() = context.contentResolver
    override var available = Settings.Secure.getIntForUser(
            contentResolver, CONTROLS_AVAILABLE, DEFAULT_ENABLED, currentUserId) != 0
        private set

    private var file = Environment.buildPath(
        context.filesDir,
        ControlsFavoritePersistenceWrapper.FILE_NAME
    )
    private var auxiliaryFile = Environment.buildPath(
        context.filesDir,
        AuxiliaryPersistenceWrapper.AUXILIARY_FILE_NAME
    )
    private val persistenceWrapper = optionalWrapper.orElseGet {
        ControlsFavoritePersistenceWrapper(
            file,
            executor,
            BackupManager(context)
        )
    }

    @VisibleForTesting
    internal var auxiliaryPersistenceWrapper = AuxiliaryPersistenceWrapper(auxiliaryFile, executor)

    private fun setValuesForUser(newUser: UserHandle) {
        Log.d(TAG, "Changing to user: $newUser")
        currentUser = newUser
        val userContext = context.createContextAsUser(currentUser, 0)
        file = Environment.buildPath(
                userContext.filesDir, ControlsFavoritePersistenceWrapper.FILE_NAME)
        auxiliaryFile = Environment.buildPath(
            userContext.filesDir, AuxiliaryPersistenceWrapper.AUXILIARY_FILE_NAME)
        persistenceWrapper.changeFileAndBackupManager(file, BackupManager(userContext))
        auxiliaryPersistenceWrapper.changeFile(auxiliaryFile)
        available = Settings.Secure.getIntForUser(contentResolver, CONTROLS_AVAILABLE,
                DEFAULT_ENABLED, newUser.identifier) != 0
        resetFavorites(available)
        bindingController.changeUser(newUser)
        listingController.changeUser(newUser)
        userChanging = false
    }

    private val userSwitchReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            if (intent.action == Intent.ACTION_USER_SWITCHED) {
                userChanging = true
                listingController.removeCallback(listingCallback)
                val newUser =
                        UserHandle.of(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, sendingUserId))
                if (currentUser == newUser) {
                    userChanging = false
                    return
                }
                setValuesForUser(newUser)
            }
        }
    }

    @VisibleForTesting
    internal val restoreFinishedReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            val user = intent.getIntExtra(Intent.EXTRA_USER_ID, UserHandle.USER_NULL)
            if (user == currentUserId) {
                executor.execute {
                    auxiliaryPersistenceWrapper.initialize()
                    listingController.removeCallback(listingCallback)
                    persistenceWrapper.storeFavorites(auxiliaryPersistenceWrapper.favorites)
                    resetFavorites(available)
                }
            }
        }
    }

    @VisibleForTesting
    internal val settingObserver = object : ContentObserver(null) {
        override fun onChange(
            selfChange: Boolean,
            uris: Collection<Uri>,
            flags: Int,
            userId: Int
        ) {
            // Do not listen to changes in the middle of user change, those will be read by the
            // user-switch receiver.
            if (userChanging || userId != currentUserId) {
                return
            }
            available = Settings.Secure.getIntForUser(contentResolver, CONTROLS_AVAILABLE,
                DEFAULT_ENABLED, currentUserId) != 0
            resetFavorites(available)
        }
    }

    // Handling of removed components

    /**
     * Check if any component has been removed and if so, remove all its favorites.
     *
     * If some component has been removed, the new set of favorites will also be saved.
     */
    private val listingCallback = object : ControlsListingController.ControlsListingCallback {
        override fun onServicesUpdated(serviceInfos: List<ControlsServiceInfo>) {
            executor.execute {
                val serviceInfoSet = serviceInfos.map(ControlsServiceInfo::componentName).toSet()
                val favoriteComponentSet = Favorites.getAllStructures().map {
                    it.componentName
                }.toSet()

                var changed = false
                favoriteComponentSet.subtract(serviceInfoSet).forEach {
                    changed = true
                    Favorites.removeStructures(it)
                    bindingController.onComponentRemoved(it)
                }

                if (auxiliaryPersistenceWrapper.favorites.isNotEmpty()) {
                    serviceInfoSet.subtract(favoriteComponentSet).forEach {
                        val toAdd = auxiliaryPersistenceWrapper.getCachedFavoritesAndRemoveFor(it)
                        if (toAdd.isNotEmpty()) {
                            changed = true
                            toAdd.forEach {
                                Favorites.replaceControls(it)
                            }
                        }
                    }
                    // Need to clear the ones that were restored immediately. This will delete
                    // them from the auxiliary file if they were not deleted. Should only do any
                    // work the first time after a restore.
                    serviceInfoSet.intersect(favoriteComponentSet).forEach {
                        auxiliaryPersistenceWrapper.getCachedFavoritesAndRemoveFor(it)
                    }
                }

                // Check if something has been added or removed, if so, store the new list
                if (changed) {
                    persistenceWrapper.storeFavorites(Favorites.getAllStructures())
                }
            }
        }
    }

    init {
        dumpManager.registerDumpable(javaClass.name, this)
        resetFavorites(available)
        userChanging = false
        broadcastDispatcher.registerReceiver(
                userSwitchReceiver,
                IntentFilter(Intent.ACTION_USER_SWITCHED),
                executor,
                UserHandle.ALL
        )
        context.registerReceiver(
            restoreFinishedReceiver,
            IntentFilter(BackupHelper.ACTION_RESTORE_FINISHED),
            PERMISSION_SELF,
            null
        )
        contentResolver.registerContentObserver(URI, false, settingObserver, UserHandle.USER_ALL)
    }

    fun destroy() {
        broadcastDispatcher.unregisterReceiver(userSwitchReceiver)
        context.unregisterReceiver(restoreFinishedReceiver)
        contentResolver.unregisterContentObserver(settingObserver)
        listingController.removeCallback(listingCallback)
    }

    private fun resetFavorites(shouldLoad: Boolean) {
        Favorites.clear()

        if (shouldLoad) {
            Favorites.load(persistenceWrapper.readFavorites())
            listingController.addCallback(listingCallback)
        }
    }

    private fun confirmAvailability(): Boolean {
        if (userChanging) {
            Log.w(TAG, "Controls not available while user is changing")
            return false
        }
        if (!available) {
            Log.d(TAG, "Controls not available")
            return false
        }
        return true
    }

    override fun loadForComponent(
        componentName: ComponentName,
        dataCallback: Consumer<ControlsController.LoadData>
    ) {
        if (!confirmAvailability()) {
            if (userChanging) {
                // Try again later, userChanging should not last forever. If so, we have bigger
                // problems. This will return a runnable that allows to cancel the delayed version,
                // it will not be able to cancel the load if
                loadCanceller = executor.executeDelayed(
                        { loadForComponent(componentName, dataCallback) },
                        USER_CHANGE_RETRY_DELAY,
                        TimeUnit.MILLISECONDS
                )
            } else {
                dataCallback.accept(createLoadDataObject(emptyList(), emptyList(), true))
            }
            return
        }
        loadCanceller = bindingController.bindAndLoad(
                componentName,
                object : ControlsBindingController.LoadCallback {
                    override fun accept(controls: List<Control>) {
                        loadCanceller = null
                        executor.execute {
                            val favoritesForComponentKeys = Favorites
                                .getControlsForComponent(componentName).map { it.controlId }

                            val changed = Favorites.updateControls(componentName, controls)
                            if (changed) {
                                persistenceWrapper.storeFavorites(Favorites.getAllStructures())
                            }
                            val removed = findRemoved(favoritesForComponentKeys.toSet(), controls)
                            val controlsWithFavorite = controls.map {
                                ControlStatus(
                                    it,
                                    componentName,
                                    it.controlId in favoritesForComponentKeys
                                )
                            }
                            val removedControls = mutableListOf<ControlStatus>()
                            Favorites.getStructuresForComponent(componentName).forEach { st ->
                                st.controls.forEach {
                                    if (it.controlId in removed) {
                                        val r = createRemovedStatus(componentName, it, st.structure)
                                        removedControls.add(r)
                                    }
                                }
                            }
                            val loadData = createLoadDataObject(
                                removedControls +
                                controlsWithFavorite,
                                favoritesForComponentKeys
                            )
                            dataCallback.accept(loadData)
                        }
                    }

                    override fun error(message: String) {
                        loadCanceller = null
                        executor.execute {
                            val controls = Favorites.getStructuresForComponent(componentName)
                                    .flatMap { st ->
                                        st.controls.map {
                                            createRemovedStatus(componentName, it, st.structure,
                                                    false)
                                        }
                                    }
                            val keys = controls.map { it.control.controlId }
                            val loadData = createLoadDataObject(controls, keys, true)
                            dataCallback.accept(loadData)
                        }
                    }
                }
        )
    }

    override fun addSeedingFavoritesCallback(callback: Consumer<Boolean>): Boolean {
        if (!seedingInProgress) return false
        executor.execute {
            // status may have changed by this point, so check again and inform the
            // caller if necessary
            if (seedingInProgress) seedingCallbacks.add(callback)
            else callback.accept(false)
        }
        return true
    }

    override fun seedFavoritesForComponent(
        componentName: ComponentName,
        callback: Consumer<Boolean>
    ) {
        if (seedingInProgress) return

        Log.i(TAG, "Beginning request to seed favorites for: $componentName")
        if (!confirmAvailability()) {
            if (userChanging) {
                // Try again later, userChanging should not last forever. If so, we have bigger
                // problems. This will return a runnable that allows to cancel the delayed version,
                // it will not be able to cancel the load if
                executor.executeDelayed(
                    { seedFavoritesForComponent(componentName, callback) },
                    USER_CHANGE_RETRY_DELAY,
                    TimeUnit.MILLISECONDS
                )
            } else {
                callback.accept(false)
            }
            return
        }
        seedingInProgress = true
        bindingController.bindAndLoadSuggested(
            componentName,
            object : ControlsBindingController.LoadCallback {
                override fun accept(controls: List<Control>) {
                    executor.execute {
                        val structureToControls =
                            ArrayMap<CharSequence, MutableList<ControlInfo>>()

                        controls.forEach {
                            val structure = it.structure ?: ""
                            val list = structureToControls.get(structure)
                                ?: mutableListOf<ControlInfo>()
                            list.add(
                                ControlInfo(it.controlId, it.title, it.subtitle, it.deviceType))
                            structureToControls.put(structure, list)
                        }

                        structureToControls.forEach {
                            (s, cs) -> Favorites.replaceControls(
                                StructureInfo(componentName, s, cs))
                        }

                        persistenceWrapper.storeFavorites(Favorites.getAllStructures())
                        callback.accept(true)
                        endSeedingCall(true)
                    }
                }

                override fun error(message: String) {
                    Log.e(TAG, "Unable to seed favorites: $message")
                    executor.execute {
                        callback.accept(false)
                        endSeedingCall(false)
                    }
                }
            }
        )
    }

    private fun endSeedingCall(state: Boolean) {
        seedingInProgress = false
        seedingCallbacks.forEach {
            it.accept(state)
        }
        seedingCallbacks.clear()
    }

    override fun cancelLoad() {
        loadCanceller?.let {
            executor.execute(it)
        }
    }

    private fun createRemovedStatus(
        componentName: ComponentName,
        controlInfo: ControlInfo,
        structure: CharSequence,
        setRemoved: Boolean = true
    ): ControlStatus {
        val intent = Intent(Intent.ACTION_MAIN).apply {
            addCategory(Intent.CATEGORY_LAUNCHER)
            this.`package` = componentName.packageName
        }
        val pendingIntent = PendingIntent.getActivity(context,
                componentName.hashCode(),
                intent,
                0)
        val control = Control.StatelessBuilder(controlInfo.controlId, pendingIntent)
                .setTitle(controlInfo.controlTitle)
                .setSubtitle(controlInfo.controlSubtitle)
                .setStructure(structure)
                .setDeviceType(controlInfo.deviceType)
                .build()
        return ControlStatus(control, componentName, true, setRemoved)
    }

    private fun findRemoved(favoriteKeys: Set<String>, list: List<Control>): Set<String> {
        val controlsKeys = list.map { it.controlId }
        return favoriteKeys.minus(controlsKeys)
    }

    override fun subscribeToFavorites(structureInfo: StructureInfo) {
        if (!confirmAvailability()) return

        bindingController.subscribe(structureInfo)
    }

    override fun unsubscribe() {
        if (!confirmAvailability()) return
        bindingController.unsubscribe()
    }

    override fun addFavorite(
        componentName: ComponentName,
        structureName: CharSequence,
        controlInfo: ControlInfo
    ) {
        if (!confirmAvailability()) return
        executor.execute {
            if (Favorites.addFavorite(componentName, structureName, controlInfo)) {
                persistenceWrapper.storeFavorites(Favorites.getAllStructures())
            }
        }
    }

    override fun replaceFavoritesForStructure(structureInfo: StructureInfo) {
        if (!confirmAvailability()) return
        executor.execute {
            Favorites.replaceControls(structureInfo)
            persistenceWrapper.storeFavorites(Favorites.getAllStructures())
        }
    }

    override fun resetFavorites() {
        executor.execute {
            Favorites.clear()
            persistenceWrapper.storeFavorites(Favorites.getAllStructures())
        }
    }

    override fun refreshStatus(componentName: ComponentName, control: Control) {
        if (!confirmAvailability()) {
            Log.d(TAG, "Controls not available")
            return
        }

        // Assume that non STATUS_OK responses may contain incomplete or invalid information about
        // the control, and do not attempt to update it
        if (control.getStatus() == Control.STATUS_OK) {
            executor.execute {
                if (Favorites.updateControls(componentName, listOf(control))) {
                    persistenceWrapper.storeFavorites(Favorites.getAllStructures())
                }
            }
        }
        uiController.onRefreshState(componentName, listOf(control))
    }

    override fun onActionResponse(componentName: ComponentName, controlId: String, response: Int) {
        if (!confirmAvailability()) return
        uiController.onActionResponse(componentName, controlId, response)
    }

    override fun action(
        componentName: ComponentName,
        controlInfo: ControlInfo,
        action: ControlAction
    ) {
        if (!confirmAvailability()) return
        bindingController.action(componentName, controlInfo, action)
    }

    override fun getFavorites(): List<StructureInfo> = Favorites.getAllStructures()

    override fun countFavoritesForComponent(componentName: ComponentName): Int =
        Favorites.getControlsForComponent(componentName).size

    override fun getFavoritesForComponent(componentName: ComponentName): List<StructureInfo> =
        Favorites.getStructuresForComponent(componentName)

    override fun getFavoritesForStructure(
        componentName: ComponentName,
        structureName: CharSequence
    ): List<ControlInfo> {
        return Favorites.getControlsForStructure(
                StructureInfo(componentName, structureName, emptyList())
        )
    }

    override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
        pw.println("ControlsController state:")
        pw.println("  Available: $available")
        pw.println("  Changing users: $userChanging")
        pw.println("  Current user: ${currentUser.identifier}")
        pw.println("  Favorites:")
        Favorites.getAllStructures().forEach { s ->
            pw.println("    ${ s }")
            s.controls.forEach { c ->
                pw.println("      ${ c }")
            }
        }
        pw.println(bindingController.toString())
    }
}

/**
 * Relies on immutable data for thread safety. When necessary to update favMap, use reassignment to
 * replace it, which will not disrupt any ongoing map traversal.
 *
 * Update/replace calls should use thread isolation to avoid race conditions.
 */
private object Favorites {
    private var favMap = mapOf<ComponentName, List<StructureInfo>>()

    fun getAllStructures(): List<StructureInfo> = favMap.flatMap { it.value }

    fun getStructuresForComponent(componentName: ComponentName): List<StructureInfo> =
        favMap.get(componentName) ?: emptyList()

    fun getControlsForStructure(structure: StructureInfo): List<ControlInfo> =
        getStructuresForComponent(structure.componentName)
            .firstOrNull { it.structure == structure.structure }
            ?.controls ?: emptyList()

    fun getControlsForComponent(componentName: ComponentName): List<ControlInfo> =
        getStructuresForComponent(componentName).flatMap { it.controls }

    fun load(structures: List<StructureInfo>) {
        favMap = structures.groupBy { it.componentName }
    }

    fun updateControls(componentName: ComponentName, controls: List<Control>): Boolean {
        val controlsById = controls.associateBy { it.controlId }

        // utilize a new map to allow for changes to structure names
        val structureToControls = mutableMapOf<CharSequence, MutableList<ControlInfo>>()

        // Must retain the current control order within each structure
        var changed = false
        getStructuresForComponent(componentName).forEach { s ->
            s.controls.forEach { c ->
                val (sName, ci) = controlsById.get(c.controlId)?.let { updatedControl ->
                    val controlInfo = if (updatedControl.title != c.controlTitle ||
                        updatedControl.subtitle != c.controlSubtitle ||
                        updatedControl.deviceType != c.deviceType) {
                        changed = true
                        c.copy(
                            controlTitle = updatedControl.title,
                            controlSubtitle = updatedControl.subtitle,
                            deviceType = updatedControl.deviceType
                        )
                    } else { c }

                    val updatedStructure = updatedControl.structure ?: ""
                    if (s.structure != updatedStructure) {
                        changed = true
                    }

                    Pair(updatedStructure, controlInfo)
                } ?: Pair(s.structure, c)

                structureToControls.getOrPut(sName, { mutableListOf() }).add(ci)
            }
        }
        if (!changed) return false

        val structures = structureToControls.map { (s, cs) -> StructureInfo(componentName, s, cs) }

        val newFavMap = favMap.toMutableMap()
        newFavMap.put(componentName, structures)
        favMap = newFavMap

        return true
    }

    fun removeStructures(componentName: ComponentName) {
        val newFavMap = favMap.toMutableMap()
        newFavMap.remove(componentName)
        favMap = newFavMap
    }

    fun addFavorite(
        componentName: ComponentName,
        structureName: CharSequence,
        controlInfo: ControlInfo
    ): Boolean {
        // Check if control is in favorites
        if (getControlsForComponent(componentName)
                        .any { it.controlId == controlInfo.controlId }) {
            return false
        }
        val structureInfo = favMap.get(componentName)
                ?.firstOrNull { it.structure == structureName }
                ?: StructureInfo(componentName, structureName, emptyList())
        val newStructureInfo = structureInfo.copy(controls = structureInfo.controls + controlInfo)
        replaceControls(newStructureInfo)
        return true
    }

    fun replaceControls(updatedStructure: StructureInfo) {
        val newFavMap = favMap.toMutableMap()
        val structures = mutableListOf<StructureInfo>()
        val componentName = updatedStructure.componentName

        var replaced = false
        getStructuresForComponent(componentName).forEach { s ->
            val newStructure = if (s.structure == updatedStructure.structure) {
                replaced = true
                updatedStructure
            } else { s }

            if (!newStructure.controls.isEmpty()) {
                structures.add(newStructure)
            }
        }

        if (!replaced && !updatedStructure.controls.isEmpty()) {
            structures.add(updatedStructure)
        }

        newFavMap.put(componentName, structures)
        favMap = newFavMap
    }

    fun clear() {
        favMap = mapOf<ComponentName, List<StructureInfo>>()
    }
}
