package com.lukouguoji.module_base.ktx

import android.app.Activity
import com.alibaba.fastjson.JSON
import dev.utils.app.permission.PermissionUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flatMapMerge
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
import org.json.JSONArray
import org.json.JSONObject
import java.text.SimpleDateFormat
import java.util.Date
import kotlin.coroutines.CoroutineContext

/**
 * @author：孟凡华
 * @date：2022/11/11
 * @desc：
 */
/********************************************************************************************
 *  String
 *********************************************************************************************/
/**
 * 非空处理
 * 空数据返回空字符串
 */
fun String?.noNull(replaceStr: String = "") = if (this.isNullOrEmpty()) replaceStr else this

/**
 * 验证是否为空数据
 */
fun Any?.verifyNullOrEmpty(msg: String): Boolean {
    var nullOrEmpty = this == null
    if (!nullOrEmpty && this is String) {
        nullOrEmpty = this.isEmpty()
    }
    if (nullOrEmpty) {
        showToast(msg)
    }
    return nullOrEmpty
}


/********************************************************************************************
 *  Boolean
 *********************************************************************************************/
fun Boolean?.toInt() = if (this == true) 1 else 0

fun String?.toBoolean() = this == "1"

fun Int?.toBoolean() = this == 1
/********************************************************************************************
 *  Date
 *********************************************************************************************/

/**
 * 格式化日期
 */
fun Date?.formatDate(format: String = "yyyy-MM-dd"): String {
    return this?.let { SimpleDateFormat(format).format(this) } ?: ""
}

/**
 * 格式化日期时间
 */
fun Date?.formatDateTime(format: String = "yyyy-MM-dd HH:mm:ss"): String {
    return this?.let { SimpleDateFormat(format).format(this) } ?: ""
}

/********************************************************************************************
 *  Json
 *********************************************************************************************/

fun Any?.toJson(format: Boolean = true): String {
    if (this == null) {
        return "{}"
    }
    val json = JSON.toJSONString(this)

    // 不格式化直接返回
    if (!format) return json

    if (json.startsWith("{")) {
        return JSONObject(json).toString(2)
    } else if (json.startsWith("[")) {
        return JSONArray(json).toString(2)
    }
    return json
}

fun Any.toMap(): HashMap<String, Any> {
    return JSON.parseObject(toJson(false), HashMap::class.java) as HashMap<String, Any>
}

fun Map<String, Any?>.trim(deep: Boolean = false): Map<String, Any?> {
    val map = HashMap<String, Any?>()
    this.forEach {
        if (it.value != null) {
            when (it.value) {
                is String -> {
                    if ((it.value as String).isNotEmpty()) {
                        map[it.key] = it.value
                    }
                }

                is Map<*, *> -> {
                    if (deep) {
                        map[it.key] = (it.value as Map<String, Any?>).trim(deep)
                    } else {
                        map[it.key] = it.value
                    }
                }

                else -> {
                    map[it.key] = it.value
                }
            }
        }
    }
    return map
}

/********************************************************************************************
 *  倒计时
 *********************************************************************************************/

fun <T> countdown(
    duration: Long,
    interval: Long,
    context: CoroutineContext = Dispatchers.Default,
    onCountdown: suspend (Long) -> T
): Flow<T> =
    flow { (duration - interval downTo 0 step interval).forEach { emit(it) } }
        .onEach { delay(interval) }
        .onStart { emit(duration) }
        .flatMapMerge { flow { emit(onCountdown(it)) } }
        .flowOn(context)

/********************************************************************************************
 *  处理
 *********************************************************************************************/
/**
 *  虽然有空安全判定,但如果空与非空需要不同的处理,依然要做!=null判定
 *  该方法旨避免判空
 */
inline fun <T, R> T?.handle(handle: (T) -> R?, nullHandle: () -> R? = { null }): R? {
    return if (this != null) handle(this) else nullHandle()
}

/**
 * 尝试执行
 */
inline fun <T, R> T?.tryCatch(handle: (T?) -> R?, cacheHandle: () -> R? = { null }): R? {
    return try {
        handle(this)
    } catch (e: Exception) {
        cacheHandle()
    }
}

///////////////////////////////////////////////////////////////////////////
// 权限
///////////////////////////////////////////////////////////////////////////

/**
 * 申请权限
 */
fun Activity.permission(
    vararg permissions: String,
    onDenied: () -> Unit = {},
    onGranted: () -> Unit = {},
) {
    PermissionUtils.permission(*permissions)
        .callback(object : PermissionUtils.PermissionCallback {
            override fun onGranted() {
                onGranted()
            }

            override fun onDenied(
                grantedList: MutableList<String>?,
                deniedList: MutableList<String>?,
                notFoundList: MutableList<String>?
            ) {
                onDenied()
            }
        })
        .request(this)
}