package com.dlc.exam.ui

import android.Manifest
import android.annotation.SuppressLint
import android.content.Intent
import android.graphics.Bitmap
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.view.LayoutInflater
import androidx.appcompat.app.AlertDialog
import com.arcsoft.face.ActiveFileInfo
import com.arcsoft.face.ErrorInfo
import com.arcsoft.face.FaceEngine
import com.bumptech.glide.Glide
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.target.Target
import com.dlc.exam.BuildConfig
import com.dlc.exam.camera.ArcSoftErrCode
import com.dlc.exam.common.CommonUtils
import com.dlc.exam.common.Constants
import com.dlc.exam.databinding.ActivitySplashBinding
import com.dlc.exam.ui.settings.PasswordDialog
import com.dlc.exam.ui.settings.SettingsActivity
import com.rc.core.log.RcLog
import com.rc.core.ui.activity.RcBaseActivity
import com.rc.core.util.ApkUpdater
import com.rc.core.util.DateUtils
import com.rc.core.util.DeviceUtils
import com.rc.httpcore.client.ApiRepository
import com.rc.httpcore.vo.response.BannerImageBean
import com.tbruyelle.rxpermissions2.RxPermissions
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import java.io.File
import java.lang.ref.WeakReference

/**
 * info
 *
 * @author ReiChin_
 */
class SplashActivity : RcBaseActivity<ActivitySplashBinding>() {

    private val weakHandler by lazy { WeakReferenceHandler(this) }
    private val weakHandlerTwo by lazy { WeakReferenceHandlerTwo(this) }
    private val weakHandlerBannerData by lazy { WeakReferenceHandlerBannerData(this) }

    override fun createViewBinding() = ActivitySplashBinding.inflate(LayoutInflater.from(this))

    @SuppressLint("SetTextI18n")
    override fun initViews(savedInstanceState: Bundle?) {
        RcLog.info(
            "versionName:${DeviceUtils.getVersionName(this)}, versionCode:${
                DeviceUtils.getVersionCode(
                    this
                )
            }"
        )
        viewBinding.versionName.text = "版本号：${DeviceUtils.getVersionName(this)}"

        viewBinding.copyRight.setOnLongClickListener {
            PasswordDialog(this) {
                val intent = Intent(this, SettingsActivity::class.java)
                startActivity(intent)
            }.show()
            true
        }

        requestPermission()

        viewBinding.banner.setOnClickListener {
            // 登录获取token
            authLogin()
        }
        viewBinding.settings.setOnLongClickListener {
            PasswordDialog(this) {
                val intent = Intent(this, SettingsActivity::class.java)
                startActivity(intent)
            }.show()
            true
        }
    }

    private fun requestPermission() {
        val disposable = RxPermissions(this)
            .request(
                Manifest.permission.WRITE_EXTERNAL_STORAGE,
                Manifest.permission.READ_EXTERNAL_STORAGE,
                Manifest.permission.CAMERA,
                Manifest.permission.READ_PHONE_STATE,
                Manifest.permission.RECORD_AUDIO,
            )
            .subscribe { granted ->
                if (granted) {
                    queryBanner()
                } else {
                    AlertDialog.Builder(this)
                        .setTitle("提示")
                        .setMessage("您必须同意所有权限才可以继续使用")
                        .setNegativeButton("确定") { _, _ ->
                            requestPermission()
                        }.show()
                }
            }
        addDisposable(disposable)
    }

    private fun queryBanner() {
        val disposable = ApiRepository.bannerImages(CommonUtils.getAndroidId(this))
            .subscribe({
                preloadBannerImg(it)
            }, {
                showDefaultImg()
            })
        addDisposable(disposable)
    }

    private val mBannerMap: MutableMap<Int, Boolean> = mutableMapOf()
    private val mBannerPathMap: MutableMap<String, String?> =
        mutableMapOf() // key: md5  value: path

    private fun preloadBannerImg(data: List<BannerImageBean>) {
        mBannerMap.clear()
        mBannerPathMap.clear()

        data.forEachIndexed { index, item ->
            val key = CommonUtils.stringToMD5(item.imgUrl) ?: ""
            Glide.with(this)
                .asBitmap()
                .load(item.imgUrl)
                .listener(object : RequestListener<Bitmap> {
                    override fun onLoadFailed(
                        e: GlideException?,
                        model: Any?,
                        target: Target<Bitmap>?,
                        isFirstResource: Boolean
                    ): Boolean {
                        mBannerMap[index] = false
                        mBannerPathMap[key] = null
                        showBanner(data)
                        return false
                    }

                    override fun onResourceReady(
                        resource: Bitmap?,
                        model: Any?,
                        target: Target<Bitmap>?,
                        dataSource: DataSource?,
                        isFirstResource: Boolean
                    ): Boolean {
                        mBannerMap[index] = true
                        mBannerPathMap[key] = saveFile(key, resource)
                        showBanner(data)
                        return false
                    }
                })
                .diskCacheStrategy(DiskCacheStrategy.RESOURCE)
                .preload()
        }
    }

    private fun saveFile(key: String, resource: Bitmap?): String {
        val fileDir = File(cacheDir, "exam/")
        if (!fileDir.exists()) fileDir.mkdir()
        val filepath = "${fileDir.absolutePath}/${key}.jpg"
        // val filePath = "${Environment.getExternalStorageDirectory().path}/${key}.jpg"
        CommonUtils.saveBitmapToFile(resource, filepath)
        return filepath
    }

    private fun showBanner(data: List<BannerImageBean>) {
        if (data.size != mBannerMap.size) return

        // 保存文件到key到sp中
        getSharedPreferences("banner", MODE_PRIVATE)
            .edit()
            .putStringSet("banner_paths", mBannerPathMap.values.toHashSet())
            .apply()

        // 使用Handler获取message对象,两种获取都可以
        val msg: Message = Handler().obtainMessage()
        msg.obj = data
        weakHandler.sendMessage(msg)
        weakHandler.sendEmptyMessage(1)
//        var index = 0
//        object : Handler(Looper.getMainLooper()) {
//            override fun handleMessage(msg: Message) {
//                if (isDestroyed) return
//
//                val activeIndex = index % data.size
//                val delayMillis = if (true == mBannerMap[activeIndex]) {
//                    Glide.with(this@SplashActivity)
//                        .load(data[activeIndex].imgUrl)
//                        .diskCacheStrategy(DiskCacheStrategy.RESOURCE)
//                        .into(viewBinding.banner)
//
//                    3000L
//                } else 0L
//
//                index++
//                if (index >= data.size) index = 0
//                sendEmptyMessageDelayed(1, delayMillis)
//            }
//        }.sendEmptyMessage(1)
    }


    private fun showDefaultImg() {
        val sp = getSharedPreferences("banner", MODE_PRIVATE)
        val bannerData = sp.getStringSet("banner_paths", mutableSetOf())?.toList()
        if (bannerData.isNullOrEmpty()) {
//            showInnerImage()
            return
        }

        val msg: Message = Handler().obtainMessage()
        msg.obj = bannerData
        weakHandlerBannerData.sendMessage(msg)
        weakHandlerBannerData.sendEmptyMessageDelayed(1, 2000)
//        var index = 0
//        object : Handler(Looper.getMainLooper()) {
//            override fun handleMessage(msg: Message) {
//                if (isDestroyed) return
//
//                val activeIndex = index % bannerData.size
//                Glide.with(this@SplashActivity)
//                    .load(bannerData[activeIndex])
//                    .diskCacheStrategy(DiskCacheStrategy.RESOURCE)
//                    .into(viewBinding.banner)
//
//                index++
//                if (index >= bannerData.size) index = 0
//                sendEmptyMessageDelayed(1, 3000)
//            }
//        }.sendEmptyMessageDelayed(1, 2000)
    }

//    private fun showInnerImage() {
//        val bannerData = arrayOf(
//            R.mipmap.img_banner3,
//            R.mipmap.img_banner2
//        )
//        var index = 0
//        object : Handler(Looper.getMainLooper()) {
//            override fun handleMessage(msg: Message) {
//                if (isDestroyed) return
//
//                viewBinding.banner.setImageResource(bannerData[index % bannerData.size])
//
//                index++
//                if (index >= bannerData.size) index = 0
//                sendEmptyMessageDelayed(1, 3000)
//            }
//        }.sendEmptyMessageDelayed(1, 2000)
//    }

    /*
     * 登录获取token
     */
    private fun authLogin() {
        showLoading("加载中...")
        val disposable = ApiRepository.authOneLogin()
            .subscribe({ success ->
                dismissLoading()
                if (success) {
//                    jumpMainActivity()
                    queryAppVersion()
                }
            }, { throwable ->
                dismissLoading()
                showNetError(throwable)
            })
        addDisposable(disposable)
    }

    private fun jumpMainActivity() {
        weakHandlerTwo.sendEmptyMessageDelayed(1, 200)
//      object : Handler(Looper.getMainLooper()) {
//            override fun handleMessage(msg: Message) {
//                initFaceEngine()
//            }
//        }.sendEmptyMessageDelayed(1, 200)
    }

    private fun queryAppVersion() {
        showLoading("版本检测中...")
        val disposable = ApiRepository.apkVersion(CommonUtils.getAndroidId(this))
            .subscribe({ data ->
                if (CommonUtils.stringParseInt(data.version) > DeviceUtils.getVersionCode(this)) {
                    // 有新版本
                    showLoading("检测到新版本，开始更新（0%）")
                    // 显示版本更新
                    downloadApk(data.apkFileUpload)
                } else {
                    // 没有新版本
                        RcLog.info("==进去了")

                }
            }, { throwable ->
                dismissLoading()
                RcLog.info("==进1去了")
                showNetError(throwable)
                jumpMainActivity()
            })
        addDisposable(disposable)
    }

    private fun downloadApk(downloadUrl: String) {
        callApkUpdateApi("2")
        ApkUpdater(this, BuildConfig.APPLICATION_ID, callback = object :
            ApkUpdater.DownloadCallback {
            override fun onProgress(progress: Int) {
                showLoading("检测到新版本，开始更新（${progress}%）")
            }

            override fun onFailed(errMsg: String?) {
                dismissLoading()
                callApkUpdateApi("0")
                showToast("下载失败，请检查网络情况重新下载")
            }

            override fun onSuccess(apkFile: String) {
                dismissLoading()
                callApkUpdateApi("1")
            }

        }).downloadApk(downloadUrl)
    }

    /*
     * state 0:升级失败; 1:升级成功; 2:升级中
     */
    private fun callApkUpdateApi(state: String) {
        val disposable = ApiRepository.onepcApkUpdate(CommonUtils.getAndroidId(this), state)
            .subscribe({ }, { })
        addDisposable(disposable)
    }

    private fun startMainActivity() {
        startActivity(Intent(this, MainActivity::class.java))
        finish()
    }

    private fun initFaceEngine() {
        activeOnlineFaceEngine {
            startMainActivity()
        }
    }

    private fun activeOnlineFaceEngine(callback: () -> Unit) {
//        if (getActiveFileInfo()) {
//            callback.invoke()
//            return
//        }

        val disposable = Observable.create<Int> { emitter ->
            RcLog.info("[face]subscribe: getRuntimeABI() ${FaceEngine.getRuntimeABI()}")

            val start = System.currentTimeMillis()
            val activeCode =
                FaceEngine.activeOnline(
                    this,
                    Constants.ArcFace.APP_ID,
                    Constants.ArcFace.SDK_KEY
                )
            RcLog.info("[face]subscribe cost: " + (System.currentTimeMillis() - start))
            emitter.onNext(activeCode)
        }.subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe({ activeCode ->
                RcLog.info("[face]激活引擎 activeCode: $activeCode")
                when (activeCode) {
                    // 激活引擎成功
                    ErrorInfo.MOK -> RcLog.info("[face]激活引擎成功")
                    // 引擎已激活，无需再次激活
                    ErrorInfo.MERR_ASF_ALREADY_ACTIVATED -> RcLog.info("[face]引擎已激活，无需再次激活")
                    // 引擎激活失败，错误码为 %d
                    else -> {
                        val message =
                            "[face] 引擎激活失败，错误码为 ${ArcSoftErrCode.decode(activeCode)}"
                        RcLog.warn(message)
                        showToast(message)
                    }
                }
                callback.invoke()

            }, { throwable ->
                throwable.printStackTrace()
            })
        addDisposable(disposable)
    }

    private fun getActiveFileInfo(): Boolean {
        val activeFileInfo = ActiveFileInfo()
        val activeCode = FaceEngine.getActiveFileInfo(this, activeFileInfo)
        return if (ErrorInfo.MOK == activeCode) {
            RcLog.info("[face] FaceEngine 已经激活")
            RcLog.info("[face] appId:${activeFileInfo.appId}")
            RcLog.info("[face] sdkKey:${activeFileInfo.sdkKey}")
            RcLog.info("[face] platform:${activeFileInfo.platform}")
            RcLog.info("[face] sdkType:${activeFileInfo.sdkType}")
            RcLog.info("[face] sdkVersion:${activeFileInfo.sdkVersion}")
            RcLog.info("[face] fileVersion:${activeFileInfo.fileVersion}")
            RcLog.info("[face] startTime:${DateUtils.formatTimestamp(activeFileInfo.startTime)}")
            RcLog.info("[face] endTime:${DateUtils.formatTimestamp(activeFileInfo.endTime)}")
            true
        } else {
            RcLog.info("[face] getActiveFileInfo failed, code is  : $activeCode")
            false
        }
    }

    // static + 弱引用  防止内存泄露
    class WeakReferenceHandler(obj: SplashActivity) : Handler(Looper.getMainLooper()) {

        private val mRef: WeakReference<SplashActivity> = WeakReference(obj)
        var index = 0
        var datas: List<BannerImageBean>? = null
        override fun handleMessage(msg: Message) {
            datas = msg.obj as List<BannerImageBean>?
            mRef.get()?.run {
                if (isDestroyed) return
                val activeIndex = index % datas!!.size
                val delayMillis = if (true == mBannerMap[activeIndex]) {
                    Glide.with(this)
                        .load(datas!![activeIndex].imgUrl)
                        .diskCacheStrategy(DiskCacheStrategy.RESOURCE)
                        .into(viewBinding.banner)

                    3000L
                } else 0L
                index++
                if (index >= datas!!.size) index = 0
                sendEmptyMessageDelayed(1, delayMillis)
            }
        }

    }

    // static + 弱引用  防止内存泄露
    class WeakReferenceHandlerTwo(obj: SplashActivity) : Handler(Looper.getMainLooper()) {
        private val mRef: WeakReference<SplashActivity> = WeakReference(obj)
        override fun handleMessage(msg: Message) {
            mRef.get()?.run {
                initFaceEngine()
            }
        }

    }

    // static + 弱引用  防止内存泄露
    class WeakReferenceHandlerBannerData(obj: SplashActivity) : Handler(Looper.getMainLooper()) {
        private val mRef: WeakReference<SplashActivity> = WeakReference(obj)
        var index = 0
        private var bannerData: List<String>? = null
        override fun handleMessage(msg: Message) {
            bannerData = msg.obj as List<String>
            mRef.get()?.run {
                if (isDestroyed) return
                val activeIndex = index % bannerData!!.size
                Glide.with(this)
                    .load(bannerData!![activeIndex])
                    .diskCacheStrategy(DiskCacheStrategy.RESOURCE)
                    .into(viewBinding.banner)
                index++
                if (index >= bannerData!!.size) index = 0
                sendEmptyMessageDelayed(1, 3000)
            }
        }

    }

    override fun onDestroy() {
        super.onDestroy()
        weakHandler.removeCallbacksAndMessages(null)
        weakHandlerTwo.removeCallbacksAndMessages(null)
        weakHandlerBannerData.removeCallbacksAndMessages(null)

    }
}