package com.ama.core.architecture.util

import android.content.Context
import android.content.Intent
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Rect
import android.net.Uri
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.provider.Settings
import android.view.Gravity
import android.view.LayoutInflater
import android.view.PixelCopy
import android.view.View
import android.view.Window
import android.view.inputmethod.InputMethodManager
import android.webkit.WebView
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.widget.AppCompatImageView
import androidx.appcompat.widget.AppCompatTextView
import androidx.core.app.NotificationManagerCompat
import androidx.core.graphics.createBitmap
import com.ama.core.architecture.BaseApp
import com.ama.core.architecture.R
import com.ama.core.architecture.databinding.LayoutToastCenterBinding
import com.ama.core.architecture.util.ResUtil.dp
import com.google.android.gms.ads.identifier.AdvertisingIdClient
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import java.util.UUID
import kotlin.random.Random


class AndroidUtil private constructor() {

    companion object {
        val gson: Gson = Gson()


        fun genRandomInt(rangeBegin: Int, rangeEnd: Int): Int {
            return Random.nextInt(rangeBegin, rangeEnd)
        }

        fun showTopToast(strRes: Int) {
            if (Looper.getMainLooper() != Looper.myLooper()) {
                val handler = Handler(Looper.getMainLooper())
                handler.post {
                    Toast.makeText(BaseApp.appContext(), strRes, Toast.LENGTH_SHORT).apply {
                        setGravity(Gravity.TOP, 0, 0)
                        show()
                    }
                }
            } else {
                Toast.makeText(BaseApp.appContext(), strRes, Toast.LENGTH_SHORT).apply {
                    setGravity(Gravity.TOP, 0, 0)
                    show()
                }
            }
        }

        fun showToast(strRes: Int) {
            if (Looper.getMainLooper() != Looper.myLooper()) {
                val handler = Handler(Looper.getMainLooper())
                handler.post {
                    Toast.makeText(BaseApp.appContext(), strRes, Toast.LENGTH_SHORT).show()
                }
            } else {
                Toast.makeText(BaseApp.appContext(), strRes, Toast.LENGTH_SHORT).show()
            }
        }

        fun showToast(str: String) {
            if (Looper.getMainLooper() != Looper.myLooper()) {
                val handler = Handler(Looper.getMainLooper())
                handler.post {
                    Toast.makeText(BaseApp.appContext(), str, Toast.LENGTH_SHORT).show()
                }
            } else {
                Toast.makeText(BaseApp.appContext(), str, Toast.LENGTH_SHORT).show()
            }
        }

        fun showCustomToast(textStr: String, iconRes: Int = 0) {
            val layout: View = LayoutInflater.from(BaseApp.appContext()).inflate(R.layout.layout_toast_center, null)

            val container: FrameLayout = layout.findViewById(R.id.toast_container)
            val params = FrameLayout.LayoutParams(240.dp.toInt(), 120.dp.toInt()).apply {
                gravity = Gravity.CENTER
            }
            container.layoutParams = params

            if (iconRes > 0) {
                layout.findViewById<ImageView>(R.id.iv_top).setImageResource(iconRes)
            }
            layout.findViewById<TextView>(R.id.tv_bottom).text = textStr

            Toast(BaseApp.appContext()).apply {
                duration = Toast.LENGTH_SHORT
                setGravity(Gravity.CENTER or Gravity.CENTER_HORIZONTAL, 0, 10)
                setView(layout)
                show()
            }
        }

        fun hideKeyboard(view: View?) {
            view?.let { v ->
                val imm = v.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
                imm.hideSoftInputFromWindow(v.windowToken, InputMethodManager.HIDE_NOT_ALWAYS)
                v.clearFocus()
            }
        }

        fun showKeyboard(view: View) {
            view.requestFocus()
            val imm = view.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
            imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT)
        }

        fun openUrl(url: String) {
            val appContext = BaseApp.appContext()
            val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
            intent.flags = FLAG_ACTIVITY_NEW_TASK
            appContext.startActivity(intent)
        }

        fun openAppNotifySettings() {
            val context = BaseApp.appContext()
            val intent = Intent()
            intent.flags = FLAG_ACTIVITY_NEW_TASK
            try {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // Android >=8
                    intent.action = Settings.ACTION_APP_NOTIFICATION_SETTINGS
                    intent.putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName)
                    intent.putExtra(Settings.EXTRA_CHANNEL_ID, context.applicationInfo.uid)

                } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // Android 5.0-7.1
                    intent.action = "android.settings.APP_NOTIFICATION_SETTINGS"
                    intent.putExtra("app_package", context.packageName)
                    intent.putExtra("app_uid", context.applicationInfo.uid)
                }

                context.startActivity(intent)
            } catch (e: Exception) {
                e.printStackTrace()
                val fallbackIntent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
                fallbackIntent.data = Uri.fromParts("package", context.packageName, null)
                context.startActivity(fallbackIntent)
            }
        }



        fun isNotificationEnabled(): Boolean {
            return NotificationManagerCompat.from(BaseApp.appContext()).areNotificationsEnabled()
        }



        fun getAppVersionInfo(): String {
            return try {
                val context = BaseApp.appContext()
                val packageManager = context.packageManager
                val packageInfo = packageManager.getPackageInfo(context.packageName, 0)
                val versionName = packageInfo.versionName
                val versionCode = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) {
                    packageInfo.longVersionCode.toString() // 在 Android 9.0 (Pie) 及以上使用 longVersionCode
                } else {
                    @Suppress("DEPRECATION")
                    packageInfo.versionCode.toString()
                }
                //"$versionName ($versionCode)"
                "$versionName"
            } catch (e: PackageManager.NameNotFoundException) {
                "Failed to get app version: ${e.message}"
            }
        }

        fun getPackageId(): String {
            return try {
                BaseApp.appContext().packageName
            } catch (e: PackageManager.NameNotFoundException) {
                "Failed to get app id: ${e.message}"
            }
        }



        fun getThumbOfView(targetView: View): Bitmap? {
            targetView.isDrawingCacheEnabled = true
            targetView.buildDrawingCache()
            val bitmap = Bitmap.createBitmap(targetView.drawingCache)
            targetView.isDrawingCacheEnabled = false
            return bitmap
        }


        fun getThumbOfView1(window: Window, targetView: View, callback: (Bitmap?) -> Unit) {
            val location = IntArray(2)
            targetView.getLocationInWindow(location)
            val (x, y) = location
            val rect = Rect(x, y, x + targetView.width, y + targetView.height)

            val destBitmap = Bitmap.createBitmap(targetView.width, targetView.height, Bitmap.Config.ARGB_8888)

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                PixelCopy.request(window, rect, destBitmap, { copyResult ->
                    if (copyResult == PixelCopy.SUCCESS) {
                        callback(destBitmap)
                    } else {
                        callback(null)
                    }
                }, Handler(Looper.getMainLooper()))
            }
        }

        fun getThumbOfView2(targetView: View): Bitmap {
            if (targetView.width <= 0 || targetView.height <= 0) {
                val widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
                val heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
                targetView.measure(widthSpec, heightSpec)
                targetView.layout(0, 0, targetView.measuredWidth, targetView.measuredHeight)
            }

            val bitmap = createBitmap(targetView.measuredWidth, targetView.measuredHeight)
            val canvas = Canvas(bitmap)
            targetView.draw(canvas)
            return bitmap
        }

        fun getThumbOfView3(targetView: View): Bitmap {
            val bitmap = Bitmap.createBitmap(
                targetView.width,
                targetView.height,
                Bitmap.Config.ARGB_8888
            )
            val canvas = Canvas(bitmap)
            targetView.draw(canvas)
            return bitmap
        }


        fun getThumbOfView4(webView : WebView): Bitmap? {
            val picture = webView.capturePicture();
            val width = picture.getWidth();
            val height = picture.getHeight();

            if (width <= 0 || height <= 0) {
                return null
            }

            try {
                val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
                val canvas = Canvas(bitmap)
                picture.draw(canvas)
                return bitmap
            } catch (e: Exception) {
                e.printStackTrace()
            }
            return null
        }



        inline fun <reified T> json2Object(jsonString: String): T? {
            return try {
                val type = object : TypeToken<T>() {}.type
                gson.fromJson(jsonString, type)
            } catch (e: Exception) {
                e.printStackTrace()
                null
            }
        }

        fun <T> object2Json(obj : T) : String {
            try {
                return gson.toJson(obj)
            } catch (e: Exception) {
                e.printStackTrace()
            }
            return ""
        }

        fun randomInt(startNum: Int, endNum: Int): Int {
            return (startNum..endNum).random()
        }

        fun randomUUid(): String {
            return UUID.randomUUID().toString().replace("-", "")
        }

        fun getGaid(): String? {
            try {
                val adInfo = AdvertisingIdClient.getAdvertisingIdInfo(BaseApp.appContext())
                return adInfo.id
            } catch (e: Exception) {

            }
            return null
        }

    }

}