/*
 * Copyright (C) 2021 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.biometrics

import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.app.ActivityTaskManager
import android.content.Context
import android.graphics.PixelFormat
import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter
import android.graphics.Rect
import android.hardware.biometrics.BiometricOverlayConstants
import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_KEYGUARD
import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_SETTINGS
import android.hardware.biometrics.SensorLocationInternal
import android.hardware.display.DisplayManager
import android.hardware.fingerprint.FingerprintManager
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
import android.hardware.fingerprint.ISidefpsController
import android.os.Handler
import android.util.Log
import android.util.RotationUtils
import android.view.Display
import android.view.Gravity
import android.view.LayoutInflater
import android.view.Surface
import android.view.View
import android.view.View.AccessibilityDelegate
import android.view.ViewPropertyAnimator
import android.view.WindowInsets
import android.view.WindowManager
import android.view.accessibility.AccessibilityEvent
import androidx.annotation.RawRes
import com.airbnb.lottie.LottieAnimationView
import com.airbnb.lottie.LottieProperty
import com.airbnb.lottie.model.KeyPath
import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.R
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.recents.OverviewProxyService
import com.android.systemui.util.concurrency.DelayableExecutor
import javax.inject.Inject

private const val TAG = "SidefpsController"

/**
 * Shows and hides the side fingerprint sensor (side-fps) overlay and handles side fps touch events.
 */
@SysUISingleton
class SidefpsController @Inject constructor(
    private val context: Context,
    private val layoutInflater: LayoutInflater,
    fingerprintManager: FingerprintManager?,
    private val windowManager: WindowManager,
    private val activityTaskManager: ActivityTaskManager,
    overviewProxyService: OverviewProxyService,
    displayManager: DisplayManager,
    @Main private val mainExecutor: DelayableExecutor,
    @Main private val handler: Handler
) {
    @VisibleForTesting
    val sensorProps: FingerprintSensorPropertiesInternal = fingerprintManager
        ?.sideFpsSensorProperties
        ?: throw IllegalStateException("no side fingerprint sensor")

    @VisibleForTesting
    val orientationListener = BiometricDisplayListener(
        context,
        displayManager,
        handler,
        BiometricDisplayListener.SensorType.SideFingerprint(sensorProps)
    ) { onOrientationChanged() }

    @VisibleForTesting
    val overviewProxyListener = object : OverviewProxyService.OverviewProxyListener {
        override fun onTaskbarStatusUpdated(visible: Boolean, stashed: Boolean) {
            overlayView?.let { view ->
                handler.postDelayed({ updateOverlayVisibility(view) }, 500)
            }
        }
    }

    private val animationDuration =
        context.resources.getInteger(android.R.integer.config_mediumAnimTime).toLong()

    private var overlayHideAnimator: ViewPropertyAnimator? = null

    private var overlayView: View? = null
        set(value) {
            field?.let { oldView ->
                windowManager.removeView(oldView)
                orientationListener.disable()
            }
            overlayHideAnimator?.cancel()
            overlayHideAnimator = null

            field = value
            field?.let { newView ->
                windowManager.addView(newView, overlayViewParams)
                updateOverlayVisibility(newView)
                orientationListener.enable()
            }
        }
    @VisibleForTesting
    internal var overlayOffsets: SensorLocationInternal = SensorLocationInternal.DEFAULT

    private val overlayViewParams = WindowManager.LayoutParams(
        WindowManager.LayoutParams.WRAP_CONTENT,
        WindowManager.LayoutParams.WRAP_CONTENT,
        WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
        Utils.FINGERPRINT_OVERLAY_LAYOUT_PARAM_FLAGS,
        PixelFormat.TRANSLUCENT
    ).apply {
        title = TAG
        fitInsetsTypes = 0 // overrides default, avoiding status bars during layout
        gravity = Gravity.TOP or Gravity.LEFT
        layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
        privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY
    }

    init {
        fingerprintManager?.setSidefpsController(
            object : ISidefpsController.Stub() {
                override fun show(
                    sensorId: Int,
                    @BiometricOverlayConstants.ShowReason reason: Int
                ) = if (reason.isReasonToShow(activityTaskManager)) show() else hide()

                override fun hide(sensorId: Int) = hide()
            })
        overviewProxyService.addCallback(overviewProxyListener)
    }

    /** Shows the side fps overlay if not already shown. */
    fun show() {
        mainExecutor.execute {
            if (overlayView == null) {
                createOverlayForDisplay()
            } else {
                Log.v(TAG, "overlay already shown")
            }
        }
    }

    /** Hides the fps overlay if shown. */
    fun hide() {
        mainExecutor.execute { overlayView = null }
    }

    private fun onOrientationChanged() {
        if (overlayView != null) {
            createOverlayForDisplay()
        }
    }

    private fun createOverlayForDisplay() {
        val view = layoutInflater.inflate(R.layout.sidefps_view, null, false)
        overlayView = view
        val display = context.display!!
        val offsets = sensorProps.getLocation(display.uniqueId).let { location ->
            if (location == null) {
                Log.w(TAG, "No location specified for display: ${display.uniqueId}")
            }
            location ?: sensorProps.location
        }
        overlayOffsets = offsets

        val lottie = view.findViewById(R.id.sidefps_animation) as LottieAnimationView
        view.rotation = display.asSideFpsAnimationRotation(offsets.isYAligned())
        lottie.setAnimation(display.asSideFpsAnimation(offsets.isYAligned()))
        lottie.addLottieOnCompositionLoadedListener {
            // Check that view is not stale, and that overlayView has not been hidden/removed
            if (overlayView != null && overlayView == view) {
                updateOverlayParams(display, it.bounds)
            }
        }
        lottie.addOverlayDynamicColor(context)

        /**
         * Intercepts TYPE_WINDOW_STATE_CHANGED accessibility event, preventing Talkback from
         * speaking @string/accessibility_fingerprint_label twice when sensor location indicator
         * is in focus
         */
        view.setAccessibilityDelegate(object : AccessibilityDelegate() {
            override fun dispatchPopulateAccessibilityEvent(
                host: View,
                event: AccessibilityEvent
            ): Boolean {
                return if (event.getEventType() === AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
                    true
                } else {
                    super.dispatchPopulateAccessibilityEvent(host, event)
                }
            }
        })
    }

    @VisibleForTesting
    internal fun updateOverlayParams(display: Display, bounds: Rect) {
        val isNaturalOrientation = display.isNaturalOrientation()
        val size = windowManager.maximumWindowMetrics.bounds
        val displayWidth = if (isNaturalOrientation) size.width() else size.height()
        val displayHeight = if (isNaturalOrientation) size.height() else size.width()
        val boundsWidth = if (isNaturalOrientation) bounds.width() else bounds.height()
        val boundsHeight = if (isNaturalOrientation) bounds.height() else bounds.width()
        val sensorBounds = if (overlayOffsets.isYAligned()) {
            Rect(
                displayWidth - boundsWidth,
                overlayOffsets.sensorLocationY,
                displayWidth,
                overlayOffsets.sensorLocationY + boundsHeight
            )
        } else {
            Rect(
                overlayOffsets.sensorLocationX,
                0,
                overlayOffsets.sensorLocationX + boundsWidth,
                boundsHeight
            )
        }

        RotationUtils.rotateBounds(
            sensorBounds,
            Rect(0, 0, displayWidth, displayHeight),
            display.rotation
        )

        overlayViewParams.x = sensorBounds.left
        overlayViewParams.y = sensorBounds.top
        windowManager.updateViewLayout(overlayView, overlayViewParams)
    }

    private fun updateOverlayVisibility(view: View) {
        if (view != overlayView) {
            return
        }
        // hide after a few seconds if the sensor is oriented down and there are
        // large overlapping system bars
        val rotation = context.display?.rotation
        if (windowManager.currentWindowMetrics.windowInsets.hasBigNavigationBar() &&
            ((rotation == Surface.ROTATION_270 && overlayOffsets.isYAligned()) ||
                    (rotation == Surface.ROTATION_180 && !overlayOffsets.isYAligned()))) {
            overlayHideAnimator = view.animate()
                .alpha(0f)
                .setStartDelay(3_000)
                .setDuration(animationDuration)
                .setListener(object : AnimatorListenerAdapter() {
                    override fun onAnimationEnd(animation: Animator) {
                        view.visibility = View.GONE
                        overlayHideAnimator = null
                    }
                })
        } else {
            overlayHideAnimator?.cancel()
            overlayHideAnimator = null
            view.alpha = 1f
            view.visibility = View.VISIBLE
        }
    }
}

private val FingerprintManager?.sideFpsSensorProperties: FingerprintSensorPropertiesInternal?
    get() = this?.sensorPropertiesInternal?.firstOrNull { it.isAnySidefpsType }

/** Returns [True] when the device has a side fingerprint sensor. */
fun FingerprintManager?.hasSideFpsSensor(): Boolean = this?.sideFpsSensorProperties != null

@BiometricOverlayConstants.ShowReason
private fun Int.isReasonToShow(activityTaskManager: ActivityTaskManager): Boolean = when (this) {
    REASON_AUTH_KEYGUARD -> false
    REASON_AUTH_SETTINGS -> when (activityTaskManager.topClass()) {
        // TODO(b/186176653): exclude fingerprint overlays from this list view
        "com.android.settings.biometrics.fingerprint.FingerprintSettings" -> false
        else -> true
    }
    else -> true
}

private fun ActivityTaskManager.topClass(): String =
    getTasks(1).firstOrNull()?.topActivity?.className ?: ""

@RawRes
private fun Display.asSideFpsAnimation(yAligned: Boolean): Int = when (rotation) {
    Surface.ROTATION_0 -> if (yAligned) R.raw.sfps_pulse else R.raw.sfps_pulse_landscape
    Surface.ROTATION_180 -> if (yAligned) R.raw.sfps_pulse else R.raw.sfps_pulse_landscape
    else -> if (yAligned) R.raw.sfps_pulse_landscape else R.raw.sfps_pulse
}

private fun Display.asSideFpsAnimationRotation(yAligned: Boolean): Float = when (rotation) {
    Surface.ROTATION_90 -> if (yAligned) 0f else 180f
    Surface.ROTATION_180 -> 180f
    Surface.ROTATION_270 -> if (yAligned) 180f else 0f
    else -> 0f
}

private fun SensorLocationInternal.isYAligned(): Boolean = sensorLocationY != 0

private fun Display.isNaturalOrientation(): Boolean =
    rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180

private fun WindowInsets.hasBigNavigationBar(): Boolean =
    getInsets(WindowInsets.Type.navigationBars()).bottom >= 70

private fun LottieAnimationView.addOverlayDynamicColor(context: Context) {
    fun update() {
        val c = context.getColor(R.color.biometric_dialog_accent)
        for (key in listOf(".blue600", ".blue400")) {
            addValueCallback(
                KeyPath(key, "**"),
                LottieProperty.COLOR_FILTER
            ) { PorterDuffColorFilter(c, PorterDuff.Mode.SRC_ATOP) }
        }
    }

    if (composition != null) {
        update()
    } else {
        addLottieOnCompositionLoadedListener { update() }
    }
}
