package com.base.browserwhite.ui.activity.scanqrc

import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.BitmapFactory
import android.graphics.Color
import android.net.Uri
import androidx.activity.addCallback
import androidx.camera.core.AspectRatio
import androidx.camera.core.Camera
import androidx.camera.core.CameraSelector
import androidx.camera.core.ImageAnalysis
import androidx.camera.core.Preview
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.core.view.updatePadding
import com.base.browserwhite.databinding.ActivityScanQrcBinding
import com.base.browserwhite.ui.activity.BaseActivity
import com.base.browserwhite.ui.views.PermissionDialog.showGerPermission
import com.base.browserwhite.utils.BarUtils
import com.base.browserwhite.utils.LogEx
import com.base.browserwhite.utils.PermissionUtils.checkCameraPermission
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min


class ScanQRCActivity : BaseActivity<ActivityScanQrcBinding>() {

    private val TAG = "ScanQRCActivity"

    override val binding: ActivityScanQrcBinding by lazy {
        ActivityScanQrcBinding.inflate(layoutInflater)
    }


    //相机
    private var camera: Camera? = null
    private var preview: Preview? = null
    private var lensFacing: Int = CameraSelector.LENS_FACING_BACK
    private var cameraProvider: ProcessCameraProvider? = null
    private lateinit var cameraExecutor: ExecutorService
    private var imageAnalyzer: ImageAnalysis? = null
    private lateinit var qrImageAnalyzer: QRImageAnalyzer


    override fun initView() {
        BarUtils.setStatusBarLightMode(this, true)
        BarUtils.setStatusBarColor(this, Color.TRANSPARENT)
        binding.root.updatePadding(top = BarUtils.getStatusBarHeight())

        val hasFlash = this.packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)
        binding.ivShoudian.isVisible = hasFlash
        if (hasFlash) {
            binding.ivShoudian.isSelected = false
        }

        if (checkCameraPermission()) {
            initCamera()
        } else {
            showGerPermission(
                desc = "This feature requires accessing your camera device to scan web QR codes. We will not transfer your data to any third-party services. Please grant permission so that we can provide you with better services",
            ) {
                launcher.launch(arrayOf(Manifest.permission.CAMERA)) { map ->
                    if (map.values.all { it }) {
                        initCamera()
                    } else {
                        finishToMain()
                    }
                }
            }

        }
    }

    override fun initListener() {
        super.initListener()
        onBackPressedDispatcher.addCallback {
            finishToMain()
        }
        binding.ivGuanbi.setOnClickListener {
            onBackPressedDispatcher.onBackPressed()
        }

        binding.ivShoudian.setOnClickListener {
            try {
                if (binding.ivShoudian.isSelected) {
                    closeFlash()
                } else {
                    openFlash()
                }
            } catch (e: Exception) {
                LogEx.logDebug(TAG, "flash $e")
                return@setOnClickListener
            }
            binding.ivShoudian.isSelected = !binding.ivShoudian.isSelected
        }
        binding.ivPhoto.setOnClickListener {

            val safIntent = Intent(Intent.ACTION_OPEN_DOCUMENT)
            safIntent.addCategory(Intent.CATEGORY_OPENABLE)
            safIntent.setType("image/*")
            launcher.launch(safIntent) {
                LogEx.logDebug(TAG, "${it.resultCode}")
                val dataIntent = it.data
                if (it.resultCode == RESULT_OK && dataIntent != null) {
                    val uri: Uri = dataIntent.data ?: Uri.EMPTY
                    val bitmap = BitmapFactory.decodeStream(contentResolver.openInputStream(uri))
                    qrImageAnalyzer.processImage(this@ScanQRCActivity, bitmap)
                }

            }
        }
    }

    private fun initCamera() {

        cameraExecutor = Executors.newSingleThreadExecutor()

        val cameraProviderFuture = ProcessCameraProvider.getInstance(this)

        cameraProviderFuture.addListener({
            //初始化相机
            cameraProvider = cameraProviderFuture.get()

            bindCameraUseCases(lensFacing)

        }, ContextCompat.getMainExecutor(this))

    }

    //绑定设置和相机实例
    private fun bindCameraUseCases(lensFacing: Int) {

        val aspectRation = aspectRatio(
            binding.previewView.width,
            binding.previewView.height
        )
        val rotation = binding.previewView.display.rotation

        // 选择相机
        val cameraSelector = CameraSelector.Builder().requireLensFacing(lensFacing).build()

        //构建预览
        preview = buildPreview(aspectRation, rotation)

        //构建图片捕捉类
//        imageCapture = buildImageCapture(aspectRation, rotation)
        qrImageAnalyzer = QRImageAnalyzer()
        qrImageAnalyzer.parseAction = { qrCodeValue, valueType ->
            startActivity(Intent(this, QrcResultActivity::class.java).putExtra("qrCodeValue", qrCodeValue))
        }

        //构建图片分析器
        imageAnalyzer = buildImageAnalysis(aspectRation, rotation) {
            it.setAnalyzer(cameraExecutor, qrImageAnalyzer)
        }

        //每次绑定需先解绑
        cameraProvider?.unbindAll()

        try {
            camera = cameraProvider?.bindToLifecycle(
                this, cameraSelector, imageAnalyzer, preview
            )
            preview?.setSurfaceProvider(binding.previewView.surfaceProvider)
        } catch (exc: Exception) {
            exc.printStackTrace()
        }
    }

    private fun buildImageAnalysis(
        aspectRatio: Int,
        rotation: Int,
        analysisAction: (imageAnalysis: ImageAnalysis) -> Unit
    ): ImageAnalysis {

        return ImageAnalysis.Builder()
            .setTargetAspectRatio(aspectRatio)
            .setTargetRotation(rotation)
            .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
            .build()
            // The analyzer can then be assigned to the instance
            .also {
                analysisAction(it)
            }
    }

    /**
     * 构建横纵比
     */
    private fun aspectRatio(width: Int, height: Int): Int {
        val previewRatio = max(width, height).toDouble() / min(width, height)
        if (abs(previewRatio - RATIO_4_3_VALUE) <= abs(previewRatio - RATIO_16_9_VALUE)) {
            return AspectRatio.RATIO_4_3
        }
        return AspectRatio.RATIO_16_9
    }

    /**
     * 构建预览图
     * @param aspectRatio 宽高比
     * @param rotation 预览图方向
     */
    private fun buildPreview(aspectRatio: Int, rotation: Int): Preview {
        return Preview.Builder()
            .setTargetAspectRatio(aspectRatio)
            .setTargetRotation(rotation)
            .build()
    }

    override fun onDestroy() {
        super.onDestroy()
        cameraExecutor.shutdown()
        imageAnalyzer?.clearAnalyzer()
        cameraProvider?.unbindAll()
    }

    companion object {
        //横纵比
        private const val RATIO_4_3_VALUE = 4.0 / 3.0
        private const val RATIO_16_9_VALUE = 16.0 / 9.0
    }


    private fun openFlash() {
//        val cameraManager = getSystemService(CAMERA_SERVICE) as CameraManager
//        cameraManager.setTorchMode(getBackCameraId(), true)
        camera?.cameraControl?.enableTorch(true)
    }

    private fun closeFlash() {
//        val cameraManager = getSystemService(CAMERA_SERVICE) as CameraManager
//        cameraManager.setTorchMode(getBackCameraId(), false)
        camera?.cameraControl?.enableTorch(false)
    }

//    private fun getBackCameraId(): String {
//        var cameraId: String? = null
//        try {
//            val cameraManager = getSystemService(CAMERA_SERVICE) as CameraManager
//            for (id in cameraManager.cameraIdList) {
//                val characteristics: CameraCharacteristics = cameraManager.getCameraCharacteristics(id)
//                if (characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_BACK) {
//                    cameraId = id
//                    break
//                }
//            }
//        } catch (e: CameraAccessException) {
//            e.printStackTrace()
//        }
//        return cameraId ?: ""
//    }


}