/*
 * Copyright (C) 2022 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.stylus

import android.hardware.BatteryState
import android.hardware.input.InputManager
import android.view.InputDevice
import com.android.systemui.CoreStartable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import javax.inject.Inject

/**
 * A [CoreStartable] that listens to USI stylus battery events, to manage the [StylusUsiPowerUI]
 * notification controller.
 */
@SysUISingleton
class StylusUsiPowerStartable
@Inject
constructor(
    private val stylusManager: StylusManager,
    private val inputManager: InputManager,
    private val stylusUsiPowerUi: StylusUsiPowerUI,
    private val featureFlags: FeatureFlags,
) : CoreStartable, StylusManager.StylusCallback {

    override fun onStylusAdded(deviceId: Int) {
        // On some devices, the addition of a new internal stylus indicates the use of a
        // USI stylus with a different vendor/product ID. We would therefore like to reset
        // the battery notification suppression, in case the user has dismissed a low battery
        // notification of the previous stylus.
        val device = inputManager.getInputDevice(deviceId) ?: return
        if (!device.isExternal) {
            stylusUsiPowerUi.updateSuppression(false)
        }
    }

    override fun onStylusUsiBatteryStateChanged(
        deviceId: Int,
        eventTimeMillis: Long,
        batteryState: BatteryState
    ) {
        if (batteryState.isPresent && batteryState.capacity > 0f) {
            stylusUsiPowerUi.updateBatteryState(deviceId, batteryState)
        }
    }

    override fun start() {
        if (!featureFlags.isEnabled(Flags.ENABLE_USI_BATTERY_NOTIFICATIONS)) return
        if (!hostDeviceSupportsStylusInput()) return

        stylusUsiPowerUi.init()
        stylusManager.registerCallback(this)
        stylusManager.startListener()
    }

    private fun hostDeviceSupportsStylusInput(): Boolean {
        return inputManager.inputDeviceIds
            .asSequence()
            .mapNotNull { inputManager.getInputDevice(it) }
            .any { it.supportsSource(InputDevice.SOURCE_STYLUS) && !it.isExternal }
    }

    companion object {
        private val TAG = StylusUsiPowerStartable::class.simpleName.orEmpty()
    }
}
