package com.develop.base.ext

import android.annotation.SuppressLint
import android.app.Application
import android.content.pm.PackageManager
import android.content.res.Resources
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable
import android.os.Build
import android.text.TextUtils
import android.util.Patterns
import android.widget.ImageView
import androidx.annotation.DimenRes
import androidx.core.content.ContextCompat
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
import com.develop.base.app.BaseApp
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import java.io.File
import java.io.IOException
import java.io.InputStream
import java.net.URI
import java.text.SimpleDateFormat
import java.util.*
import java.util.regex.Pattern

fun globalApp(): Application = BaseApp.application

fun globalRes(): Resources = globalApp().resources

// ------------------------------Any扩展-------------------------------------
fun Any.toJson(): String = Json.encodeToString(this)

fun Any.dimenRes(@DimenRes res: Int): Int {
    return globalApp().resources.getDimensionPixelSize(res)
}

// ------------------------------String扩展-------------------------------------
fun String.fromJson(): Any = Json.decodeFromString(this)

fun String.getHost(): String {
    var hostUrl = this
    if (!(hostUrl.startsWith("http://") || hostUrl.startsWith("https://"))) {
        hostUrl = "http://$this"
    }
    var returnVal = ""
    try {
        val uri = URI(hostUrl)
        returnVal = uri.host
    } catch (e: Exception) {
    }
    if (returnVal.endsWith(".html") || returnVal.endsWith(".htm")) {
        returnVal = ""
    }
    return "http://$returnVal"
}

fun String.isHttpUrl(): Boolean = Patterns.WEB_URL.matcher(this).matches()

fun String.assetsUri2Bitmap(): Bitmap? {
    val path = this
    var image: Bitmap? = null
    val am = globalApp().resources.assets
    try {
        val stream: InputStream = am.open(path)
        image = BitmapFactory.decodeStream(stream)
        stream.close()
    } catch (e: IOException) {
        e.printStackTrace()
    }
    return image
}

fun String.jsonSpiltField(fieldName: String): String {
    if (fieldName.isEmpty()) {
        return ""
    }
    val regex = "(?<=(\"$fieldName\":\")).*?(?=(\"))"
    val pattern = Pattern.compile(regex)
    val matcher = pattern.matcher(this)
    while (matcher.find()) {
        if (!TextUtils.isEmpty(matcher.group().trim { it <= ' ' })) {
            return matcher.group().trim { it <= ' ' }
        }
    }
    return ""
}

fun String.createFolder() {
    val file = File(this)
    if (!file.exists()) {
        file.mkdirs()
    }
}

fun String.deleteFile(): Boolean {
    val file = File(this)
    if (!file.exists()) {
        return false
    }
    return file.delete()
}

fun timeStamp2Time(timeSeconds: Long, format: String = "yyyy/MM/dd HH:mm"): String? {
    val date = Date(timeSeconds * 1000)
    return SimpleDateFormat(format, Locale.getDefault()).format(date)
}

fun String.toCacheFolder(): String = globalApp().externalCacheDir.toString() + "/" + this

// ------------------------------Int扩展-------------------------------------
fun Int.resId2Drawable(): Drawable? = ContextCompat.getDrawable(globalApp(), this)

fun Int.resId2Dimension(): Float = BaseApp.application.resources.getDimension(this)

// ------------------------------RequestBody扩展-------------------------------------
fun Map<String, String>.genMultipartBody(): RequestBody {
    val builder = MultipartBody.Builder()
    builder.setType(MultipartBody.FORM)//表单类型
    this.forEach {
        builder.addFormDataPart(it.key, it.value)
    }
    return builder.build()
}

fun Map<String, String>.genRequestBody(): Map<String, RequestBody> {
    val requestBodyMap: MutableMap<String, RequestBody> = HashMap()
    for (key in this.keys) {
        val requestBody: RequestBody =
            (if (this[key] == null) "" else this[key] ?: ""
                    ).toRequestBody("text/plain".toMediaTypeOrNull())
        requestBodyMap[key] = requestBody
    }
    return requestBodyMap
}

fun GlobalApp(): Application {
    return BaseApp.application
}

/**
 * 获取SN
 * @return
 */
fun getSN(): String {
    var serial: String
    //通过android.os获取sn号
//    val append = "03403015"
    var append = "01703015"
    val plInfo =  GlobalApp().applicationContext.packageManager.getPackageInfo(GlobalApp().applicationContext.packageName,
        PackageManager.GET_META_DATA)
    var vi = plInfo.versionName.split(".");
    append = (vi[1] + vi[0])
    try {
        serial = Build.SERIAL
        return if (serial != "" && serial != "unknown") "${append}$serial" else "${append}8888"
    } catch (e: java.lang.Exception) {
        serial = "${append}8888"
    }

    //通过反射获取sn号
    try {
        val c = Class.forName("android.os.SystemProperties")
        val get = c.getMethod("get", String::class.java)
        serial = get.invoke(c, "ro.serialno") as String
        if (serial != "" && serial != "unknown") return serial

        //9.0及以上无法获取到sn，此方法为补充，能够获取到多数高版本手机 sn
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) serial = Build.getSerial()
    } catch (e: java.lang.Exception) {
        serial = "${append}8888"
    }
    return serial
}

fun ImageView.load(data: Any?) {
    Glide.with(this.context).load(data)
        .diskCacheStrategy(DiskCacheStrategy.RESOURCE)
        .into(this)
}

fun ImageView.load(data: Any?, error: Int) {
    Glide.with(this.context).load(data)
        .error(error)
        .transition(DrawableTransitionOptions.withCrossFade())
        .into(this)
}