package com.base.scanqrclear.ui.main

import android.Manifest
import android.app.Activity
import android.content.Intent
import android.content.pm.PackageManager
import android.hardware.camera2.CameraMetadata.FLASH_MODE_OFF
import android.net.Uri
import android.view.View
import android.widget.SeekBar
import androidx.camera.core.ImageCapture.FLASH_MODE_ON
import androidx.lifecycle.lifecycleScope
import com.base.scanqrclear.R
import com.base.scanqrclear.ads.AdsMgr
import com.base.scanqrclear.ads.AdsShowCallBack
import com.base.scanqrclear.base.BaseFragment
import com.base.scanqrclear.bean.ContractUIBean.Companion.createContractBean
import com.base.scanqrclear.bean.ContractUIBean.Companion.isContractQR
import com.base.scanqrclear.bean.EmailUIBean.Companion.createEmailBean
import com.base.scanqrclear.bean.EmailUIBean.Companion.isEmailQR
import com.base.scanqrclear.bean.EventUIBean.Companion.createEventBean
import com.base.scanqrclear.bean.EventUIBean.Companion.isEventQR
import com.base.scanqrclear.bean.MessageUIBean.Companion.createMessageBean
import com.base.scanqrclear.bean.MessageUIBean.Companion.isMessageQR
import com.base.scanqrclear.bean.ProductUIBean
import com.base.scanqrclear.bean.ScanBean.Companion.CREATE_TYPE_SCAN
import com.base.scanqrclear.bean.TelephoneUIBean.Companion.createTelephoneBean
import com.base.scanqrclear.bean.TelephoneUIBean.Companion.isTelephoneQR
import com.base.scanqrclear.bean.TextUIBean
import com.base.scanqrclear.bean.WebsiteUIBean.Companion.createWebsiteBean
import com.base.scanqrclear.bean.WebsiteUIBean.Companion.isWebsiteQR
import com.base.scanqrclear.bean.WifiUIBean.Companion.createWifiBean
import com.base.scanqrclear.bean.WifiUIBean.Companion.isWifiQR
import com.base.scanqrclear.databinding.FragmentScanBinding
import com.base.scanqrclear.qr.QRImageAnalyzer
import com.base.scanqrclear.ui.contact.ContractCodeActivity
import com.base.scanqrclear.ui.email.EmailCodeActivity
import com.base.scanqrclear.ui.event.EventCodeActivity
import com.base.scanqrclear.ui.message.MessageCodeActivity
import com.base.scanqrclear.ui.product.ProductCodeActivity
import com.base.scanqrclear.ui.telephone.TelephoneCodeActivity
import com.base.scanqrclear.ui.text.TextCodeActivity
import com.base.scanqrclear.ui.website.WebsiteCodeActivity
import com.base.scanqrclear.ui.wifi.WifiCodeActivity
import com.base.scanqrclear.utils.BitmapUtils.uriToBitmap
import com.base.scanqrclear.utils.IntentUtils.intentSafPickImage
import com.base.scanqrclear.utils.LogEx
import com.base.scanqrclear.utils.PermissionUtils.checkCameraPermission
import com.google.gson.Gson
import com.google.mlkit.vision.barcode.common.Barcode
import com.gyf.immersionbar.ktx.immersionBar
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.util.concurrent.atomic.AtomicBoolean


class ScanFragment : BaseFragment<FragmentScanBinding>(FragmentScanBinding::inflate) {


    private var zoomPair = Pair(0f, 100f)

    private val qrImageAnalyzer: QRImageAnalyzer = QRImageAnalyzer()

    override fun initView() {
        super.initView()
    }

    override fun onResumeOneShoot() {
        super.onResumeOneShoot()

        if (requireContext().checkCameraPermission()) {
            initCamera()
        } else {
            val activity = requireActivity() as ScanAc?
            activity ?: return
            activity.launcher.launch(arrayOf(Manifest.permission.CAMERA)) {
                initCamera()
            }
        }
    }


    /**
     * 初始化相机
     */
    private fun initCamera() {
        val hasFlash = requireContext().packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)
        if (!hasFlash) {
            binding.flFlash.visibility = View.GONE
        }
        val activity = requireActivity() as ScanAc?
        activity ?: return

        qrImageAnalyzer.parseAction = { qrCodeValue, valueType ->
            handleScan(qrCodeValue, valueType)
        }

        activity.cameraUtils?.cameraReadyCallBack = {

            //变焦
            if (activity.cameraUtils?.isZoomSupported() != true) {
                binding.llZoom.visibility = View.GONE
            } else {
                zoomPair = activity.cameraUtils?.getZoomRange() ?: Pair(0f, 100f)
                LogEx.logDebug(TAG, "zoomPair=${zoomPair.first} ${zoomPair.second}")
                binding.seekbar.max = ((zoomPair.second - zoomPair.first) * 10).toInt()
            }

            //闪光灯
            activity.cameraUtils?.getFlashState()?.observe(this) { state ->
                if (state == FLASH_MODE_OFF) {
                    binding.ivFlash.setImageResource(R.mipmap.shandian_off)
                    binding.flFlash.setOnClickListener {
                        activity.cameraUtils?.turnOnFlash()
                    }
                }
                if (state == FLASH_MODE_ON) {
                    binding.ivFlash.setImageResource(R.mipmap.shnadian_on)
                    binding.flFlash.setOnClickListener {
                        activity.cameraUtils?.turnOffFlash()
                    }
                }
            }
        }
    }

    private var scanJump = AtomicBoolean(false)

    /**
     * 处理扫描结果
     */
    private fun handleScan(qrCodeValue: String, valueType: Int) {

        LogEx.logDebug(TAG, "qrCodeValue=$qrCodeValue valueType=$valueType isResumed=$isResumed")
        if (!isResumed) return
        val activity = requireActivity() as ScanAc?
        activity ?: return

        if (valueType == Barcode.TYPE_PRODUCT) {
            if (scanJump.get()) return
            scanJump.set(true)
            AdsMgr.showInsert(activity, true, object : AdsShowCallBack() {
                override fun close(where: Int) {
                    jumpProductCodeActivity(activity, qrCodeValue)
                }

                override fun failed(where: Int) {
                    jumpProductCodeActivity(activity, qrCodeValue)
                }

                override fun googleFailed(where: Int) {
                    jumpProductCodeActivity(activity, qrCodeValue)
                }
            })
            return
        }
        if (isMessageQR(qrCodeValue)) {
            if (scanJump.get()) return
            scanJump.set(true)
            AdsMgr.showInsert(activity, true, object : AdsShowCallBack() {
                override fun close(where: Int) {
                    jumpMessageCodeActivity(activity, qrCodeValue)
                }

                override fun failed(where: Int) {
                    jumpMessageCodeActivity(activity, qrCodeValue)
                }

                override fun googleFailed(where: Int) {
                    jumpMessageCodeActivity(activity, qrCodeValue)
                }
            })
            return
        }
        if (isContractQR(qrCodeValue)) {
            if (scanJump.get()) return
            scanJump.set(true)
            AdsMgr.showInsert(activity, true, object : AdsShowCallBack() {
                override fun close(where: Int) {
                    jumpContractCodeActivity(activity, qrCodeValue)
                }

                override fun failed(where: Int) {
                    jumpContractCodeActivity(activity, qrCodeValue)
                }

                override fun googleFailed(where: Int) {
                    jumpContractCodeActivity(activity, qrCodeValue)
                }
            })
            return
        }
        if (isTelephoneQR(qrCodeValue)) {
            if (scanJump.get()) return
            scanJump.set(true)
            AdsMgr.showInsert(activity, true, object : AdsShowCallBack() {
                override fun close(where: Int) {
                    jumpTelephoneCodeActivity(activity, qrCodeValue)
                }

                override fun failed(where: Int) {
                    jumpTelephoneCodeActivity(activity, qrCodeValue)
                }

                override fun googleFailed(where: Int) {
                    jumpTelephoneCodeActivity(activity, qrCodeValue)
                }
            })
            return
        }
        if (isEventQR(qrCodeValue)) {
            if (scanJump.get()) return
            scanJump.set(true)
            AdsMgr.showInsert(activity, true, object : AdsShowCallBack() {
                override fun close(where: Int) {
                    jumpEventCodeActivity(activity, qrCodeValue)
                }

                override fun failed(where: Int) {
                    jumpEventCodeActivity(activity, qrCodeValue)
                }

                override fun googleFailed(where: Int) {
                    jumpEventCodeActivity(activity, qrCodeValue)
                }
            })
            return
        }

        if (isWifiQR(qrCodeValue)) {
            if (scanJump.get()) return
            scanJump.set(true)
            AdsMgr.showInsert(activity, true, object : AdsShowCallBack() {
                override fun close(where: Int) {
                    jumpWifiCodeActivity(activity, qrCodeValue)
                }

                override fun failed(where: Int) {
                    jumpWifiCodeActivity(activity, qrCodeValue)
                }

                override fun googleFailed(where: Int) {
                    jumpWifiCodeActivity(activity, qrCodeValue)
                }
            })
            return
        }

        if (isEmailQR(qrCodeValue)) {
            if (scanJump.get()) return
            scanJump.set(true)
            AdsMgr.showInsert(activity, true, object : AdsShowCallBack() {
                override fun close(where: Int) {
                    jumpEmailCodeActivity(activity, qrCodeValue)
                }

                override fun failed(where: Int) {
                    jumpEmailCodeActivity(activity, qrCodeValue)
                }

                override fun googleFailed(where: Int) {
                    jumpEmailCodeActivity(activity, qrCodeValue)
                }
            })
            return
        }

        if (isWebsiteQR(qrCodeValue)) {
            if (scanJump.get()) return
            scanJump.set(true)
            AdsMgr.showInsert(activity, true, object : AdsShowCallBack() {
                override fun close(where: Int) {
                    jumpWebsiteCodeActivity(activity, qrCodeValue)
                }

                override fun failed(where: Int) {
                    jumpWebsiteCodeActivity(activity, qrCodeValue)

                }

                override fun googleFailed(where: Int) {
                    jumpWebsiteCodeActivity(activity, qrCodeValue)

                }
            })
            return
        }

        if (valueType == Barcode.TYPE_TEXT) {
            if (scanJump.get()) return
            scanJump.set(true)
            AdsMgr.showInsert(activity, true, object : AdsShowCallBack() {
                override fun close(where: Int) {
                    jumpTextCodeActivity(activity, qrCodeValue)
                }

                override fun failed(where: Int) {
                    jumpTextCodeActivity(activity, qrCodeValue)
                }

                override fun googleFailed(where: Int) {
                    jumpTextCodeActivity(activity, qrCodeValue)

                }
            })
            return
        }
    }

    private fun jumpMessageCodeActivity(activity: Activity, qrCodeValue: String) {
        activity.startActivity(Intent(activity, MessageCodeActivity::class.java).apply {
            val bean = createMessageBean(qrCodeValue)
            bean.needCreate = true
            bean.createType = CREATE_TYPE_SCAN
            putExtra("data", Gson().toJson(bean))
        })
    }

    private fun jumpContractCodeActivity(activity: Activity, qrCodeValue: String) {
        activity.startActivity(Intent(activity, ContractCodeActivity::class.java).apply {
            val bean = createContractBean(qrCodeValue)
            bean.needCreate = true
            bean.createType = CREATE_TYPE_SCAN
            putExtra("data", Gson().toJson(bean))
        })
    }

    private fun jumpTelephoneCodeActivity(activity: Activity, qrCodeValue: String) {
        activity.startActivity(Intent(activity, TelephoneCodeActivity::class.java).apply {
            val bean = createTelephoneBean(qrCodeValue)
            bean.needCreate = true
            bean.createType = CREATE_TYPE_SCAN
            putExtra("data", Gson().toJson(bean))
        })
    }

    private fun jumpEventCodeActivity(activity: Activity, qrCodeValue: String) {
        activity.startActivity(Intent(activity, EventCodeActivity::class.java).apply {
            val bean = createEventBean(qrCodeValue)
            bean.needCreate = true
            bean.createType = CREATE_TYPE_SCAN
            putExtra("data", Gson().toJson(bean))
        })
    }

    private fun jumpTextCodeActivity(activity: Activity, qrCodeValue: String) {
        activity.startActivity(Intent(activity, TextCodeActivity::class.java).apply {
            val bean = TextUIBean()
            bean.content = qrCodeValue
            bean.needCreate = true
            bean.createType = CREATE_TYPE_SCAN
            putExtra("data", Gson().toJson(bean))
        })
    }

    private fun jumpWebsiteCodeActivity(activity: Activity, qrCodeValue: String) {
        activity.startActivity(Intent(activity, WebsiteCodeActivity::class.java).apply {
            val bean = createWebsiteBean(qrCodeValue)
            bean.needCreate = true
            bean.createType = CREATE_TYPE_SCAN
            putExtra("data", Gson().toJson(bean))
        })
    }

    private fun jumpEmailCodeActivity(activity: Activity, qrCodeValue: String) {
        activity.startActivity(Intent(activity, EmailCodeActivity::class.java).apply {
            val bean = createEmailBean(qrCodeValue)
            bean.needCreate = true
            bean.createType = CREATE_TYPE_SCAN
            putExtra("data", Gson().toJson(bean))
        })
    }

    private fun jumpWifiCodeActivity(activity: Activity, qrCodeValue: String) {
        activity.startActivity(Intent(activity, WifiCodeActivity::class.java).apply {
            val bean = createWifiBean(qrCodeValue)
            bean.needCreate = true
            bean.createType = CREATE_TYPE_SCAN
            putExtra("data", Gson().toJson(bean))
        })
    }

    private fun jumpProductCodeActivity(activity: Activity, qrCodeValue: String) {
        activity.startActivity(Intent(activity, ProductCodeActivity::class.java).apply {
            val bean = ProductUIBean()
            bean.content = qrCodeValue
            bean.needCreate = true
            bean.createType = CREATE_TYPE_SCAN
            putExtra("data", Gson().toJson(bean))
        })
    }


    override fun onDestroy() {
        super.onDestroy()
        val activity = requireActivity() as ScanAc?
        activity?.cameraUtils?.unBind()
    }

    override fun initListener() {
        super.initListener()
        binding.flImage.setOnClickListener {
            val activity = requireActivity() as ScanAc?
            val intent = intentSafPickImage()
            activity?.launcher?.launch(intent) { result ->
                val uri: Uri? = result.data?.data
                uri ?: return@launch
                lifecycleScope.launch(Dispatchers.IO) {
                    val bitmap = requireContext().uriToBitmap(uri)
                    bitmap?.let {
                        launch(Dispatchers.Main) {
                            qrImageAnalyzer.processImage(requireContext(), bitmap)
                        }
                    }
                }
            }
        }
        binding.flFlash.setOnClickListener {
            val activity = requireActivity() as ScanAc?
            activity?.cameraUtils?.turnOnFlash()
        }
        binding.seekbar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
            override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
                if (fromUser) {
                    val zoom = (zoomPair.first + seekBar.progress / 10f)
                    val activity = requireActivity() as ScanAc?
                    activity?.cameraUtils?.setZoomRate(zoom)
                }
            }

            override fun onStartTrackingTouch(seekBar: SeekBar) {
            }

            override fun onStopTrackingTouch(seekBar: SeekBar) {

            }
        })
        binding.flReduce.setOnClickListener {
            val activity = requireActivity() as ScanAc?
            activity?.cameraUtils?.setZoomRate(zoomPair.first)
            binding.seekbar.progress = 0
        }
        binding.flAdd.setOnClickListener {
            val activity = requireActivity() as ScanAc?
            activity?.cameraUtils?.setZoomRate(zoomPair.second)
            binding.seekbar.progress = binding.seekbar.max
        }
    }


    private var analyzerbind = AtomicBoolean(false)

    private fun bindAnalyzer() {
        if (analyzerbind.get()) return
        analyzerbind.set(true)
        val activity = requireActivity() as ScanAc?
        activity ?: return
        activity.cameraUtils?.startBind(binding.previewView, qrImageAnalyzer)
    }

    private fun unBindAnalyzer() {
        val activity = requireActivity() as ScanAc?
        activity?.cameraUtils?.unBind()
        analyzerbind.set(false)
    }

    override fun onResume() {
        super.onResume()
        scanJump.set(false)
        immersionBar {
            statusBarColor("#00FFFFFF")
        }
        bindAnalyzer()
    }

    override fun onPause() {
        super.onPause()
        unBindAnalyzer()
    }

}