package com.lukouguoji.module_base.cache

import androidx.lifecycle.MutableLiveData
import com.lukouguoji.module_base.ktx.loge
import com.lukouguoji.module_base.ktx.toJson
import com.lukouguoji.module_base.util.DownloadUtil
import dev.DevUtils
import dev.utils.common.FileUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File


open class FileCacheModel {

    /**
     * 缓存列表
     */
    val cacheList = MutableLiveData<ArrayList<File>>()

    init {
        refreshCacheList()
    }

    /**
     * 保存文件
     * 可以通过该方法获取文件
     */
    open suspend fun saveFile(
        url: String,
        onProgress: (progress: Int) -> Unit = {
            showLog(
                mapOf(
                    "url" to url,
                    "progress" to it
                ).toJson()
            )
        },
        onSuccess: (file: File) -> Unit = {
            showLog(
                "下载完成 : ${
                    mapOf(
                        "url" to url,
                        "filePath" to it.path
                    )
                }"
            )
        },
        onError: (message: String) -> Unit = {
            showLog("下载失败 : $it")
        },
    ) {
        //先判断并创建文件夹
        if (!FileUtils.createOrExistsDir(folderPath())) {
            return
        }
        //输出文件的地址
        val outputFilePath = getFilePath(url)
        showLog("生成文件地址: $outputFilePath")

        //判断文件是否已缓存
        if (fileIsExitByUrl(url)) {
            onSuccess(File(outputFilePath))
            return
        }

        //下载文件
        DownloadUtil.download(
            url,
            outputFilePath,
            onProgress,
            {
                //通知数据改变
                refreshCacheList()
                onSuccess(it)
            }, onError
        )
    }

    /**
     * 刷新缓存列表
     */
    private fun refreshCacheList() {
        GlobalScope.launch(Dispatchers.IO) {
            if (FileUtils.createOrExistsDir(folderPath())) {
                //获取文件夹
                val folder = File(folderPath())
                //获取文件夹下所有文件
                val list =
                    folder.listFiles { file -> file?.isFile ?: false }?.toList()
                //通知数据
                cacheList.postValue(arrayListOf<File>().apply {
                    addAll(list ?: emptyList())
                })
            }
        }
    }

    /**
     * 清理缓存
     */
    suspend fun cleanCache() {
        withContext(Dispatchers.IO) {
            FileUtils.deleteAllInDir(folderPath())
        }
    }

    /**
     * 获取缓存大小
     */
    fun getCacheSize(): String {
        return FileUtils.getDirSize(folderPath())
    }

    /**
     * 文件网络地址转文件本地名称
     */
    open fun url2FileName(url: String): String {
        if (url.isEmpty()) {
            throw NullPointerException("文件地址不能为空")
        }
        //最后一个斜杠的位置
        val lastIndexOfSlash = url.lastIndexOf("/")
        //如果没有斜杠,或斜杠在最后一个,则以整个url作为文件名
        if (lastIndexOfSlash == -1 || lastIndexOfSlash == (url.length - 1)) {
            return url
        }

        val fileName = url.substring(lastIndexOfSlash + 1)
        showLog("生成的文件名称: $fileName\n url: $url")
        return fileName
    }

    /**
     * 文件夹路径
     * 每种文件缓存,单独使用一个文件夹,方便获取类型完整数据或清除数据
     */
    open fun folderPath(): String {
        return DevUtils.getContext().filesDir.toString() + "/cacheFiles/"
    }

    /**
     * 获取文件完整路径
     */
    fun getFilePath(url: String): String = folderPath() + url2FileName(url)

    /**
     * 通过url判断文件是否存在
     */
    fun fileIsExitByUrl(url: String): Boolean {
        return FileUtils.isFileExists(getFilePath(url))
    }

    /**
     * 展示日志,统一管理该类的日志显示
     */
    private fun showLog(msg: String) {
        loge("文件缓存 :  $msg")
    }

}