/*
 * Copyright (C) 2020 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.doze

import android.view.Display
import com.android.systemui.doze.DozeLog.Reason
import com.android.systemui.doze.DozeLog.reasonToString
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.LogLevel.DEBUG
import com.android.systemui.log.LogLevel.ERROR
import com.android.systemui.log.LogLevel.INFO
import com.android.systemui.log.dagger.DozeLog
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
import javax.inject.Inject

/** Interface for logging messages to the [DozeLog]. */
class DozeLogger @Inject constructor(
    @DozeLog private val buffer: LogBuffer
) {
    fun logPickupWakeup(isWithinVibrationThreshold: Boolean) {
        buffer.log(TAG, DEBUG, {
            bool1 = isWithinVibrationThreshold
        }, {
            "PickupWakeup withinVibrationThreshold=$bool1"
        })
    }

    fun logPulseStart(@Reason reason: Int) {
        buffer.log(TAG, INFO, {
            int1 = reason
        }, {
            "Pulse start, reason=${reasonToString(int1)}"
        })
    }

    fun logPulseFinish() {
        buffer.log(TAG, INFO, {}, { "Pulse finish" })
    }

    fun logNotificationPulse() {
        buffer.log(TAG, INFO, {}, { "Notification pulse" })
    }

    fun logDozing(isDozing: Boolean) {
        buffer.log(TAG, INFO, {
            bool1 = isDozing
        }, {
            "Dozing=$bool1"
        })
    }

    fun logDozingSuppressed(isDozingSuppressed: Boolean) {
        buffer.log(TAG, INFO, {
            bool1 = isDozingSuppressed
        }, {
            "DozingSuppressed=$bool1"
        })
    }

    fun logFling(
        expand: Boolean,
        aboveThreshold: Boolean,
        thresholdNeeded: Boolean,
        screenOnFromTouch: Boolean
    ) {
        buffer.log(TAG, DEBUG, {
            bool1 = expand
            bool2 = aboveThreshold
            bool3 = thresholdNeeded
            bool4 = screenOnFromTouch
        }, {
            "Fling expand=$bool1 aboveThreshold=$bool2 thresholdNeeded=$bool3 " +
                    "screenOnFromTouch=$bool4"
        })
    }

    fun logEmergencyCall() {
        buffer.log(TAG, INFO, {}, { "Emergency call" })
    }

    fun logKeyguardBouncerChanged(isShowing: Boolean) {
        buffer.log(TAG, INFO, {
            bool1 = isShowing
        }, {
            "Keyguard bouncer changed, showing=$bool1"
        })
    }

    fun logScreenOn(isPulsing: Boolean) {
        buffer.log(TAG, INFO, {
            bool1 = isPulsing
        }, {
            "Screen on, pulsing=$bool1"
        })
    }

    fun logScreenOff(why: Int) {
        buffer.log(TAG, INFO, {
            int1 = why
        }, {
            "Screen off, why=$int1"
        })
    }

    fun logMissedTick(delay: String) {
        buffer.log(TAG, ERROR, {
            str1 = delay
        }, {
            "Missed AOD time tick by $str1"
        })
    }

    fun logTimeTickScheduled(whenAt: Long, triggerAt: Long) {
        buffer.log(TAG, DEBUG, {
            long1 = whenAt
            long2 = triggerAt
        }, {
            "Time tick scheduledAt=${DATE_FORMAT.format(Date(long1))} " +
                    "triggerAt=${DATE_FORMAT.format(Date(long2))}"
        })
    }

    fun logKeyguardVisibilityChange(isShowing: Boolean) {
        buffer.log(TAG, INFO, {
            bool1 = isShowing
        }, {
            "Keyguard visibility change, isShowing=$bool1"
        })
    }

    fun logDozeStateChanged(state: DozeMachine.State) {
        buffer.log(TAG, INFO, {
            str1 = state.name
        }, {
            "Doze state changed to $str1"
        })
    }

    fun logStateChangedSent(state: DozeMachine.State) {
        buffer.log(TAG, INFO, {
            str1 = state.name
        }, {
            "Doze state sent to all DozeMachineParts stateSent=$str1"
        })
    }

    fun logDisplayStateChanged(displayState: Int) {
        buffer.log(TAG, INFO, {
            str1 = Display.stateToString(displayState)
        }, {
            "Display state changed to $str1"
        })
    }

    fun logWakeDisplay(isAwake: Boolean, @Reason reason: Int) {
        buffer.log(TAG, DEBUG, {
            bool1 = isAwake
            int1 = reason
        }, {
            "Display wakefulness changed, isAwake=$bool1, reason=${reasonToString(int1)}"
        })
    }

    fun logProximityResult(isNear: Boolean, millis: Long, @Reason reason: Int) {
        buffer.log(TAG, DEBUG, {
            bool1 = isNear
            long1 = millis
            int1 = reason
        }, {
            "Proximity result reason=${reasonToString(int1)} near=$bool1 millis=$long1"
        })
    }

    fun logPulseDropped(pulsePending: Boolean, state: DozeMachine.State, blocked: Boolean) {
        buffer.log(TAG, INFO, {
            bool1 = pulsePending
            str1 = state.name
            bool2 = blocked
        }, {
            "Pulse dropped, pulsePending=$bool1 state=$str1 blocked=$bool2"
        })
    }

    fun logPulseDropped(reason: String) {
        buffer.log(TAG, INFO, {
            str1 = reason
        }, {
            "Pulse dropped, why=$str1"
        })
    }

    fun logPulseTouchDisabledByProx(disabled: Boolean) {
        buffer.log(TAG, DEBUG, {
            bool1 = disabled
        }, {
            "Pulse touch modified by prox, disabled=$bool1"
        })
    }

    fun logSensorTriggered(@Reason reason: Int) {
        buffer.log(TAG, DEBUG, {
            int1 = reason
        }, {
            "Sensor triggered, type=${reasonToString(int1)}"
        })
    }

    fun logDozeSuppressed(state: DozeMachine.State) {
        buffer.log(TAG, INFO, {
            str1 = state.name
        }, {
            "Doze state suppressed, state=$str1"
        })
    }

    fun logDozeScreenBrightness(brightness: Int) {
        buffer.log(TAG, INFO, {
            int1 = brightness
        }, {
            "Doze screen brightness set, brightness=$int1"
        })
    }

    fun logSetAodDimmingScrim(scrimOpacity: Long) {
        buffer.log(TAG, INFO, {
            long1 = scrimOpacity
        }, {
            "Doze aod dimming scrim opacity set, opacity=$long1"
        })
    }
}

private const val TAG = "DozeLog"

val DATE_FORMAT = SimpleDateFormat("MM-dd HH:mm:ss.S", Locale.US)
