package com.dronex.rec.recording

import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.content.pm.ServiceInfo
import android.os.Build
import android.os.IBinder
import android.os.PowerManager
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import androidx.lifecycle.LifecycleService
import com.dronex.rec.AppConstants
import com.dronex.rec.MainActivity

class RecordingForegroundService : LifecycleService() {
    private var wakeLock: PowerManager.WakeLock? = null

    override fun onCreate() {
        super.onCreate()
        instance = this
        createNotificationChannel()
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        super.onStartCommand(intent, flags, startId)
        when (intent?.action) {
            AppConstants.RECORDING_ACTION_START -> {
                acquireWakeLock()
                val notification = buildNotification("正在录制")
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                    startForeground(
                            NOTIFICATION_ID,
                            notification,
                            foregroundServiceTypes(),
                    )
                } else {
                    startForeground(NOTIFICATION_ID, notification)
                }
                isRunning = true
            }
            AppConstants.RECORDING_ACTION_STOP -> {
                releaseWakeLock()
                stopForeground(STOP_FOREGROUND_REMOVE)
                isRunning = false
                stopSelf()
            }
        }
        return START_STICKY
    }

    override fun onDestroy() {
        releaseWakeLock()
        isRunning = false
        if (instance === this) {
            instance = null
        }
        super.onDestroy()
    }

    override fun onBind(intent: Intent): IBinder? {
        super.onBind(intent)
        return null
    }

    private fun acquireWakeLock() {
        if (wakeLock?.isHeld == true) return
        val manager = getSystemService(PowerManager::class.java) ?: return
        wakeLock =
                manager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKE_LOCK_TAG).apply {
                    setReferenceCounted(false)
                    acquire(4 * 60 * 60 * 1000L)
                }
    }

    private fun releaseWakeLock() {
        wakeLock?.let {
            if (it.isHeld) {
                it.release()
            }
        }
        wakeLock = null
    }

    private fun createNotificationChannel() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return
        val channel =
                NotificationChannel(
                                CHANNEL_ID,
                                "录制服务",
                                NotificationManager.IMPORTANCE_LOW,
                        )
                        .apply {
                            description = "保持相机录制在后台与息屏时继续运行"
                            setShowBadge(false)
                        }
        val manager = getSystemService(NotificationManager::class.java)
        manager?.createNotificationChannel(channel)
    }

    private fun foregroundServiceTypes(): Int {
        var types = ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA
        if (hasRecordAudioPermission()) {
            types = types or ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE
        }
        return types
    }

    private fun hasRecordAudioPermission(): Boolean {
        return ContextCompat.checkSelfPermission(
                this,
                android.Manifest.permission.RECORD_AUDIO,
        ) == PackageManager.PERMISSION_GRANTED
    }

    private fun buildNotification(content: String): Notification {
        val launchIntent =
                Intent(this, MainActivity::class.java).apply {
                    flags = Intent.FLAG_ACTIVITY_SINGLE_TOP
                }
        val pendingIntent =
                PendingIntent.getActivity(
                        this,
                        0,
                        launchIntent,
                        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
                )

        return NotificationCompat.Builder(this, CHANNEL_ID)
                .setContentTitle("录制进行中")
                .setContentText(content)
                .setSmallIcon(android.R.drawable.presence_video_online)
                .setOngoing(true)
                .setContentIntent(pendingIntent)
                .setCategory(NotificationCompat.CATEGORY_SERVICE)
                .setPriority(NotificationCompat.PRIORITY_LOW)
                .build()
    }

    companion object {
        const val CHANNEL_ID = "recording_foreground"
        const val NOTIFICATION_ID = 1001
        private const val WAKE_LOCK_TAG = "record_tool:recording_wake_lock"

        @Volatile var isRunning: Boolean = false

        @Volatile var instance: RecordingForegroundService? = null

        fun start(context: Context) {
            val intent =
                    Intent(context, RecordingForegroundService::class.java).apply {
                        action = AppConstants.RECORDING_ACTION_START
                    }
            ContextCompatStart.startForegroundService(context, intent)
        }

        fun stop(context: Context) {
            val intent =
                    Intent(context, RecordingForegroundService::class.java).apply {
                        action = AppConstants.RECORDING_ACTION_STOP
                    }
            context.startService(intent)
        }
    }
}

private object ContextCompatStart {
    fun startForegroundService(context: Context, intent: Intent) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            context.startForegroundService(intent)
        } else {
            context.startService(intent)
        }
    }
}
