package com.develop.food.base.repo

import android.app.Application
import android.os.Environment
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.room.Room
import com.blankj.utilcode.util.FileUtils
import com.blankj.utilcode.util.ToastUtils
import com.blankj.utilcode.util.ZipUtils
import com.develop.base.BuildConfig
import com.develop.food.base.FoodCookBaseApp
import com.develop.food.base.common.CURRENT_USER_ID_TAG
import com.develop.food.base.repo.db.FOOD_MIGRATION_2_3
import com.develop.food.base.repo.db.FoodDatabase
import com.develop.food.base.repo.db.UserDatabase
import com.develop.food.base.utils.GlobalApp
import com.develop.food.base.utils.MmkvUtils
import com.develop.food.base.utils.StringUtils
import com.develop.food.base.utils.ThreadUtils
import com.develop.food.base.utils.setUpdateRecipeTime
import java.io.File
import java.io.FileWriter
import java.text.SimpleDateFormat
import java.util.Date
import java.util.concurrent.CountDownLatch

object FoodDataProvider {
    private val SYSTEM_MODE = BuildConfig.DEBUG
    private val RES_DST_PARENT =   File("system/media")
    private val TARGET_DST_PARENT = Environment.getExternalStorageDirectory()
    private val preparedLock = CountDownLatch(1)
    private var foodDatabase: FoodDatabase? = null
    private var userDatabase: UserDatabase? = null
    private val prepareLiveData = MutableLiveData<Boolean>()
    private val ZIP_PATH = File(RES_DST_PARENT, "cofa_cooking.zip")
    private val RES_DST_PATH = File(TARGET_DST_PARENT, "cofa_cooking")
    private val SUCCESS_FLAG = File(TARGET_DST_PARENT, "success.lock")
    private var UPDATE_TIME = ""
    init {
        if (!RES_DST_PARENT.exists()) {
            RES_DST_PARENT.mkdirs()
        }
    }
    fun  setUpdateTime(time:String){
        this.UPDATE_TIME = time
    }

    fun prepareData(application: Application) {
        var isSuccess = true
        ThreadUtils.runOnWorkThread(Runnable {
            if (RES_DST_PATH.exists()) {
                validateDatabaseFile()
                preparedLock.countDown()
                return@Runnable
            }
//            val allFiles = RES_DST_PARENT.listFiles() ?: emptyArray()
//            var targetZipFile: File? = null
//            for (file in allFiles) {
//                if (file.isDirectory) {
//                    continue
//                }
//                if (file.name.endsWith("cofa_cooking.zip")) {
//                    targetZipFile = file
//                    break
//                }
//            }
//            if (targetZipFile == null) {
//                FileKit.copyAssetsFile(
//                    application,
//                    "cofa_cooking.zip",
//                    File(RES_DST_PARENT, "cofa_cooking.zip").absolutePath
//                )
//                targetZipFile = File(RES_DST_PARENT, "cofa_cooking.zip")
//            }
            FileUtils.delete(RES_DST_PATH)
            try {
                val targetZipFile = ZIP_PATH
                val start = System.currentTimeMillis()

                StringUtils.unZip(targetZipFile.absolutePath, TARGET_DST_PARENT.absolutePath)
                Log.d(
                    "FoodDataProvider", "cost time:${System.currentTimeMillis() - start}"
                )
                val sqliteFile = File(RES_DST_PATH, "sqlite.db")
                if (!sqliteFile.exists() || sqliteFile.length() == 0L) {
                    // 1s后再重试
                    Thread.sleep(1000)
                    FileUtils.delete(RES_DST_PATH)
                    ZipUtils.unzipFile(targetZipFile, TARGET_DST_PARENT)
                }
                validateDatabaseFile()
            } catch (ex: Exception) {
                ex.printStackTrace()
                isSuccess = false
                ToastUtils.showShort("数据包解压失败! 请检查数据包")
                prepareLiveData.postValue(false)
            }
            if (isSuccess) {
                prepareLiveData.postValue(true)

                //解压完成写入文件标识
                val currentDate = Date()
                val dateFormat = SimpleDateFormat("yyyyMMddhhmmss")
                val formattedDate = dateFormat.format(currentDate)
                var fw = FileWriter(SUCCESS_FLAG)
                //保存本地更新时间，方便到时候OTA更新
                setUpdateRecipeTime(UPDATE_TIME)
                fw.write(formattedDate)
                fw.flush()
                fw.close()

                Log.d("FoodDataProvider", "数据解压成功!")
            } else {
                Log.d("FoodDataProvider", "数据包解压失败! 请检查数据包")
                prepareLiveData.postValue(false)
            }
            Log.d("FoodDataProvider", "数据解压成功!")
            preparedLock.countDown()
        })
    }

    private fun validateDatabaseFile() {
        val dbFile = RES_DST_PATH.listFiles { it ->
            it.name.endsWith(".db")
        }
        if (dbFile.isNullOrEmpty()) {
            ToastUtils.showShort("数据包文件结构有误, 请检查数据包")
        } else {
            Log.d("FoodDataProvider", "数据包校验成功")
            initFoodDataBase()
        }
        prepareLiveData.postValue(true)
    }

    fun getResource(relativePath: String): File {
        preparedLock.await()
        return File(RES_DST_PATH, relativePath)
    }

    fun getResourcePath(relativePath: String?): String {
        if (relativePath == null) {
            return ""
        }
        if (relativePath?.startsWith("http") == true) {
            return relativePath
        }
//        preparedLock.await()
        return "${TARGET_DST_PARENT.absolutePath}/$relativePath"
    }

    fun getResourceDir(): File {
        return RES_DST_PATH
    }

    /**获取菜品资源包文件*/
    fun getExtRecipeResourceDir(): File {
        return TARGET_DST_PARENT
    }

    fun isResourceDownload(recipeNum: String): Boolean {
        return getResourceConfigJsonPath(recipeNum).exists()
    }

    fun getResourceConfigJsonPath(recipeNum: String): File {
        val relPath = "_data/recipe/${recipeNum}/data.json"
        return File(RES_DST_PATH, relPath)
    }

    /**
     * 作兼容处理, 资源包里的图片格式可能是jpg或png
     */
    fun getImagePath(relativePath: String?): String {
        if (relativePath?.startsWith("http") == true) {
            return relativePath
        }
        preparedLock.await()
        if (relativePath == null) {
            return ""
        }
        val resFile = getResource(relativePath)
        if (resFile.exists()) {
            return resFile.absolutePath
        }
        return if (relativePath.endsWith("png")) {
            "${RES_DST_PATH}/${relativePath.replace("png", "jpg")}"
        } else {
            "${RES_DST_PATH}/${relativePath.replace("jpg", "png")}"
        }
    }

    fun deleteRecipeResource(recipeNum: String) {
        val relPath = "_data/recipe/${recipeNum}"
        val dir = File(RES_DST_PATH, relPath)
        if (dir.exists()) {
            try {
                FileUtils.delete(dir)
            }catch (ex: Exception) {
                ex.printStackTrace()
            }
        }
    }

    fun deleteAll() {
        if (RES_DST_PATH.exists()) {
            try {
                FileUtils.delete(RES_DST_PATH)
            }catch (ex: Exception) {
                ex.printStackTrace()
            }
        }
    }

    @Synchronized
    fun getDatabase(): FoodDatabase {
        if (foodDatabase != null) {
            return foodDatabase!!
        }
        preparedLock.await()
        initFoodDataBase()
        return foodDatabase!!
    }

    @Synchronized
    fun getUserDatabase(): UserDatabase {
        if (userDatabase != null) {
            return userDatabase!!
        }
        userDatabase = Room.databaseBuilder(
            FoodCookBaseApp.application,
            UserDatabase::class.java,
            "/sdcard/User/userInfo"
        ).allowMainThreadQueries().build()
        return userDatabase!!
    }

    fun getPrepareLiveData(): LiveData<Boolean> {
        return prepareLiveData
    }
    fun checkDataExit(): Boolean {
        val result = prepareLiveData.value == true
        if (!result) {
            prepareData(GlobalApp())
        }
        return prepareLiveData.value == true
    }


    private fun initFoodDataBase() {
        //处理数据库
        StringUtils.modifyDatabase()

        val dbFile = File(RES_DST_PATH, "sqlite.db")
        foodDatabase = Room.databaseBuilder(
             FoodCookBaseApp.application, FoodDatabase::class.java, "sqlite.db"
        ).allowMainThreadQueries().createFromFile(dbFile).addMigrations(FOOD_MIGRATION_2_3).build()

    }
}

val CURRENT_USER_ID get() = MmkvUtils.getLong(CURRENT_USER_ID_TAG) ?: 10001L