package com.develop.food.base.utils


import android.app.Application
import android.graphics.*
import android.graphics.drawable.Drawable
import android.os.Build
import android.util.Patterns
import androidx.annotation.DimenRes
import androidx.core.content.ContextCompat
import androidx.lifecycle.MutableLiveData
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.room.TypeConverter
import com.develop.base.BuildConfig
import com.develop.food.base.FoodCookBaseApp
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
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.lang.reflect.Type
import java.net.URI
import java.text.DecimalFormat
import java.text.SimpleDateFormat
import java.util.*


/**
 * Json扩展
 */
fun Any.toJson(): String = Gson().toJson(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 Date.now(format: String = "yyyy-MM-dd HH:mm:ss"): String = SimpleDateFormat(format).format(this)

/**
 * 判断字符串是否为URL
 *
 * @param urls 需要判断的String类型url
 * @return true:是URL；false:不是URL
 */
fun String.isHttpUrl(): Boolean {
    val urls = this
    return Patterns.WEB_URL.matcher(urls).matches()
}


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

fun ResDrawable(res: Int): Drawable? {
    return ContextCompat.getDrawable(GlobalApp(), res)
}

fun ResDimension(res: Int): Float {
    return FoodCookBaseApp.application.resources.getDimension(res)
}

fun <T> T?.ifNull(isNull: () -> Unit, isNotNull: (t: T) -> Unit) {
    this?.let {
        isNotNull.invoke(it)
        return
    }
    isNull.invoke()
}

fun <T> mutableLiveData() =
    lazy { MutableLiveData<T>() }

fun Number?.asInt(): Int {
    if (this == null) {
        return 0
    }
    return toInt()
}

fun Matrix.mapPoint(p: PointF) {
    val f = floatArrayOf(p.x, p.y)
    mapPoints(f)
    p.x = f[0]
    p.y = f[1]
}

fun <T> MutableList<T>.ensureSize(requireSize: Int, creator: () -> T) {
    val diffSize = this.size - requireSize
    if (diffSize >= 0) {
        return
    }
    for (i in 0 until diffSize) {
        add(creator.invoke())
    }
}

fun RecyclerView.linearLayoutManager(): LinearLayoutManager {
    return layoutManager as LinearLayoutManager
}

fun String?.isUrl(): Boolean {
    return this != null && this.startsWith("http")
}

fun String.getFileNameExcludeSuffix(): String {
    val fileName = File(this).name
    val dotIndex = fileName.lastIndexOf(".")
    if (dotIndex < 0) {
        return fileName
    }
    return fileName.substring(0, dotIndex)
}

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

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

fun Long.keepTwoDigits(): String {
    if (this in 0..9) {
        return "0${this}"
    }
    return this.toString()
}

fun String.cacheFolder(): String {
    val file = this
    return GlobalApp().externalCacheDir.toString() + "/" + file
}

fun String.addComma(): String {
    val str = this
    val decimalFormat = DecimalFormat(",###")
    return decimalFormat.format(str.toDouble())
}

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

/**
 * 判断2个时间大小
 * yyyy-MM-dd HH:mm 格式（自己可以修改成想要的时间格式）
 * @param startTime
 * @param endTime
 * @return
 */
fun timeCompare(startTime: String, endTime: String, format: String = "yyyy-MM-dd HH:mm:ss"): Int {
    var i = 0
    //注意：传过来的时间格式必须要和这里填入的时间格式相同
    val dateFormat = SimpleDateFormat(format, Locale.US)
    try {
        val date1 = dateFormat.parse(startTime) //开始时间
        val date2 = dateFormat.parse(endTime) //结束时间
        // 1 结束时间小于开始时间 2 开始时间与结束时间相同 3 结束时间大于开始时间
        when {
            date2.time < date1.time -> {
                //结束时间小于开始时间
                i = 1
            }
            date2.time == date1.time -> {
                //开始时间与结束时间相同
                i = 0
            }
            date2.time > date1.time -> {
                //结束时间大于开始时间
                i = -1
            }
        }
    } catch (e: java.lang.Exception) {
    }
    return i
}

/**
 * 从Assets/中读取图片
 */
fun String.getImageFromAssetsFile(): Bitmap? {
    val path = this
    var image: Bitmap? = null
    val am = GlobalApp().resources.assets
    try {
        val `is`: InputStream = am.open(path)
        image = BitmapFactory.decodeStream(`is`)
        `is`.close()
    } catch (e: IOException) {
        e.printStackTrace()
    }
    return image
}

class StringTypeConverter {
    var gson = Gson()

    @TypeConverter
    fun stringToSomeObjectList(data: String): List<String> {
        val listType: Type = object : TypeToken<List<String>>() {}.type
        return gson.fromJson(data, listType)
    }

    @TypeConverter
    fun someObjectListToString(someObjects: List<String>): String {
        return gson.toJson(someObjects)
    }
}

class IntTypeConverter {
    var gson = Gson()

    @TypeConverter
    fun stringToSomeObjectList(data: String): List<Int> {
        val listType: Type = object : TypeToken<List<Int>>() {}.type
        return gson.fromJson(data, listType)
    }

    @TypeConverter
    fun someObjectListToString(someObjects: List<Int>): String {
        return gson.toJson(someObjects)
    }
}

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

/**
 * 获取SN
 * @return
 */
fun getSN(): String {
    var serial: String
    //通过android.os获取sn号
//    val append = "03403015"
    val append = "01703015"
    try {
        serial = Build.SERIAL
        return if (serial != "" && serial != "unknown") "${append}$serial" else "${append}888888"
    } catch (e: java.lang.Exception) {
        serial = "${append}888888"
    }

    //通过反射获取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}888888"
    }
    return serial
}