package com.dlc.chemical.ui

import android.Manifest
import android.annotation.SuppressLint
import android.app.ActivityManager
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.provider.Settings
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.dlc.chemical.BuildConfig
import com.dlc.chemical.camera.ArcSoftErrCode
import com.dlc.chemical.common.CommonUtils
import com.dlc.chemical.common.Constants
import com.dlc.chemical.databinding.ActivitySplashBinding
import com.dlc.chemical.sp.ConfLogoSp
import com.dlc.chemical.ui.settings.PasswordDialog
import com.dlc.chemical.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.tbruyelle.rxpermissions2.RxPermissions
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import java.lang.ref.WeakReference
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale


/**
 * info
 *
 * @author ReiChin_
 */
class SplashActivity : RcBaseActivity<ActivitySplashBinding>() {
    private val weakHandler by lazy {  WeakReferenceHandler(this) }
    override fun createViewBinding() = ActivitySplashBinding.inflate(LayoutInflater.from(this))

    @SuppressLint("SetTextI18n")
    override fun initViews(savedInstanceState: Bundle?) {
        val activityManager = getSystemService(ACTIVITY_SERVICE) as ActivityManager
        RcLog.info("versionName:${DeviceUtils.getVersionName(this)}, versionCode:${DeviceUtils.getVersionCode(this)}, deviceId:${CommonUtils.getAndroidId()}, memoryClass:${activityManager.memoryClass}m")
        viewBinding.versionName.text = "版本号：${DeviceUtils.getVersionName(this)}"

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

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

        requestPermission()
    }

    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) {
                    queryLogoConf()
                } else {
                    AlertDialog.Builder(this)
                        .setTitle("提示")
                        .setMessage("您必须同意所有权限才可以继续使用")
                        .setNegativeButton("确定") { _, _ ->
                            requestPermission()
                        }.show()
                }
            }
        addDisposable(disposable)
    }

    private fun queryLogoConf() {
        showLoading("加载中...")
        val disposable = ApiRepository.queryLogoConfInfo()
            .subscribe({ data ->
                dismissLoading()
                ConfLogoSp.saveConfLogo(this, data)
                jumpMainActivity()
            }, { throwable ->
                dismissLoading()
                showNetError(throwable)
                throwable.printStackTrace()
            })
        addDisposable(disposable)
    }

    private fun jumpMainActivity() {
        weakHandler.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())
            .subscribe({ data ->
                if (CommonUtils.stringParseInt(data.version) > DeviceUtils.getVersionCode(this)) {
                    // 有新版本
                    showLoading("检测到新版本，开始更新（0%）")
                    // 显示版本更新
                    downloadApk(data.apkFileUpload)
                } else {
                    // 没有新版本
                    jumpMainActivity()
                }
            }, { throwable ->
                dismissLoading()
                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(), state)
            .subscribe({ }, { })
        addDisposable(disposable)
    }

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

    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
        }
    }

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

    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(
                    applicationContext,
                    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)
                    }
                }
                getActiveFileInfo()
                callback.invoke()
            }, { throwable ->
                throwable.printStackTrace()
                callback.invoke()
            })
        addDisposable(disposable)
    }

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

    override fun onDestroy() {
        weakHandler.removeCallbacksAndMessages(null)
        super.onDestroy()
    }
}