package com.adealink.weparty.share.poster.comp

import android.Manifest
import android.annotation.SuppressLint
import android.graphics.Bitmap
import android.os.Build
import android.view.LayoutInflater
import android.view.View
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import com.adealink.frame.aab.util.getCompatString
import com.adealink.frame.base.AppBase
import com.adealink.frame.coroutine.dispatcher.Dispatcher
import com.adealink.frame.ext.copyToAlbum
import com.adealink.frame.log.Log
import com.adealink.frame.mvvm.view.ViewComponent
import com.adealink.frame.util.AppUtil
import com.adealink.frame.util.ViewShotUtil
import com.adealink.frame.util.getFileName
import com.adealink.frame.util.onClick
import com.adealink.weparty.commonui.BaseActivity
import com.adealink.weparty.commonui.toast.util.showToast
import com.adealink.weparty.commonui.widget.CommonDialog
import com.adealink.weparty.constant.STORAGE_PERMISSION_DIALOG
import com.adealink.weparty.permission.PermissionUtils
import com.adealink.weparty.share.R
import com.adealink.weparty.share.data.TAG_SHARE_POSTER
import com.adealink.weparty.share.databinding.LayoutSharePosterShotBinding
import com.adealink.weparty.storage.file.FilePath
import com.google.zxing.BarcodeFormat
import com.google.zxing.EncodeHintType
import com.journeyapps.barcodescanner.BarcodeEncoder
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
import com.adealink.weparty.R as APP_R

class SharePosterComp(
    lifecycleOwner: LifecycleOwner,
    val shareButton: View
) : ViewComponent(lifecycleOwner) {

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

    private fun initView() {
        shareButton.onClick {
            sharePoster()
        }
    }

    //保存图片需要检查存储权限
    @SuppressLint("CheckResult")
    private fun checkStoragePermissionAndSaveImg() {
        val context = activity ?: return
        val permission = getMediaImagePermission()
        if (PermissionUtils.hasPermissions(context, *permission)) {
            sharePoster()
        } else {
            PermissionUtils.getRxPermissions(context)
                .request(*permission).subscribe { granted ->
                    if (granted) {
                        sharePoster()
                    } else {
                        showPermissionNoGrantedDialog()
                    }
                }
        }
    }

    private fun sharePoster() {
        (activity as? BaseActivity)?.showLoading()
        viewLifecycleOwner.lifecycleScope.launch {
            var qrCodeImg: Bitmap?
            try {
                qrCodeImg = generateQRCode()
                val posterPath = generatePosterBitmap(qrCodeImg)
                savePosterToAlbum(posterPath)
                showToast(R.string.share_save_poster_success)
            } catch (e: Exception) {
                Log.d(TAG_SHARE_POSTER, "sharePoster fail, for ${e.message}", e)
                showToast(R.string.share_save_poster_fail)
            } finally {
                (activity as? BaseActivity)?.dismissLoading()
            }
        }
    }

    private suspend fun generateQRCode(): Bitmap? {
        return withContext(Dispatcher.WENEXT_THREAD_POOL) {
            val qrCodeText = "Hello, 扫码呀!!!!"
            try {
                val barcodeEncoder = BarcodeEncoder()
                val bitmap = barcodeEncoder.encodeBitmap(
                    qrCodeText,
                    BarcodeFormat.QR_CODE,
                    400, 400,
                    mapOf<EncodeHintType, Any>(
                        EncodeHintType.CHARACTER_SET to "UTF-8",
                        EncodeHintType.MARGIN to "2"
                    )
                )
                return@withContext bitmap
            } catch (e: Exception) {
                Log.e(TAG_SHARE_POSTER, "generateQRCode fail, ${e.message}", e)
            }
            return@withContext null
        }
    }

    private suspend fun generatePosterBitmap(qrCode: Bitmap?): String? {
        return withContext(Dispatcher.WENEXT_THREAD_POOL) {
            //加载模版布局
            val shotView =
                LayoutInflater.from(context).inflate(R.layout.layout_share_poster_shot, null)

            // TODO: 海报内容要动态填入
            val shotViewBinding = LayoutSharePosterShotBinding.bind(shotView)
            shotViewBinding.tvNews.text = "新闻标题123123123123"

            shotViewBinding.ivPhoto.setImageUrl("https://im.sdk.qcloud.com/download/tuikit-resource/community-cover/community_cover_default.png")
            shotViewBinding.tvName.text = "用户名字"
            shotViewBinding.tvEvaluate.text = "4.9"
            shotViewBinding.tvLocation.text = "雅加达"
            shotViewBinding.tvSummary.text =
                "自我介绍总结,自我介绍总结,自我介绍总结,自我介绍总结"

            shotViewBinding.vGame1.ivGame.setImageUrl("https://im.sdk.qcloud.com/download/tuikit-resource/group-avatar/group_avatar_default.png")
            shotViewBinding.vGame1.tvGame.text = "Game1"

            shotViewBinding.vGame2.ivGame.setImageUrl("https://im.sdk.qcloud.com/download/tuikit-resource/group-avatar/group_avatar_default.png")
            shotViewBinding.vGame2.tvGame.text = "Game2"

            shotViewBinding.vGame3.ivGame.setImageUrl("https://im.sdk.qcloud.com/download/tuikit-resource/group-avatar/group_avatar_default.png")
            shotViewBinding.vGame3.tvGame.text = "Game3"

            if (qrCode != null && !qrCode.isRecycled) {
                shotViewBinding.ivQrCode.setImageBitmap(qrCode)
            }

            //测量视图（重要！）
            shotView.measure(
                View.MeasureSpec.makeMeasureSpec(SHOT_WIDTH, View.MeasureSpec.EXACTLY),
                View.MeasureSpec.makeMeasureSpec(SHOT_HEIGHT, View.MeasureSpec.EXACTLY)
            )
            //布局视图
            shotView.layout(0, 0, shotView.measuredWidth, shotView.measuredHeight)

            //创建 Bitmap 并绘制
            val savePath = FilePath.shareImagePath
            if (savePath.isNullOrEmpty()) {
                Log.e(TAG_SHARE_POSTER, "shotViewAndSave fail, for shareImagePath is null.")
                return@withContext null
            }
            val shotPath = ViewShotUtil.of(shotView)
                .setSavePath(savePath)
                .setFilename(SHOT_IMG_NAME)
                .minWidth(SHOT_WIDTH)
                .maxWidth(SHOT_WIDTH)
                .toPNG()
                .save()
            if (shotPath.isNullOrEmpty()) {
                Log.e(
                    TAG_SHARE_POSTER,
                    "shotViewAndSave fail, for ViewShot fail."
                )
                return@withContext null
            }
            return@withContext shotPath
        }
    }

    private suspend fun savePosterToAlbum(posterPath: String?) {
        return withContext(Dispatcher.WENEXT_THREAD_POOL) {
            if (posterPath.isNullOrEmpty()) {
                Log.d(TAG_SHARE_POSTER, "saveImage fail, for shotView fail.")
                return@withContext
            }
            val imgName = getFileName(posterPath)
            if (imgName.isNullOrEmpty()) {
                Log.d(TAG_SHARE_POSTER, "saveImage fail, for can not find imgName.")
                return@withContext
            }
            withContext(Dispatcher.WENEXT_THREAD_POOL) {
                File(posterPath).copyToAlbum(AppUtil.appContext, imgName, AppBase.appName)
            }
        }
    }


    private fun getMediaImagePermission(): Array<String> {
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            arrayOf(Manifest.permission.READ_MEDIA_IMAGES)
        } else {
            arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE)
        }
    }

    private fun showPermissionNoGrantedDialog() {
        val permissionDialog = CommonDialog.Builder()
            .message(getCompatString(APP_R.string.toast_storage_permission_no_granted))
            .onPositive {
                PermissionUtils.startPermissionSettingActivity(activity)
            }
            .dismissAfterClick(true)
            .setShowDefaultCancel(true)
            .build()
        permissionDialog.show(fragmentManager, STORAGE_PERMISSION_DIALOG)
    }

    companion object {

        const val SHOT_IMG_NAME = "poster"
        const val SHOT_WIDTH = 750 //像素
        const val SHOT_HEIGHT = 1492 //像素
    }

}