package com.test.mydemo3.util

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.BitmapFactory
import android.graphics.drawable.BitmapDrawable
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.MediaStore
import android.util.Log
import android.util.TypedValue
import com.test.mydemo3.model.FileBean
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.io.File
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.Date

object FileUtil {

    val EXTERNAL_STORAGE: String = Environment.getExternalStorageDirectory().path

    const val TEXT_MIME_TYPE = "text/plain"
    const val ZIP_MIME_TYPE = "application/zip"
    const val RAR_MIME_TYPE = "application/x-rar-compressed"
    const val ZIP_7Z_MIME_TYPE ="application/x-7z-compressed"
    const val PDF_MIME_TYPE = "application/pdf"
    const val WORD_MIME_TYPE = "application/msword"
    const val EXCEL_MIME_TYPE = "application/vnd.ms-excel"
    const val PPT_MIME_TYPE = "application/vnd.ms-powerpoint"
    const val APK_MIME_TYPE = "application/vnd.android.package-archive"
    const val MP3_MIME_TYPE = "audio/mpeg"
    const val WAV_MIME_TYPE = "audio/x-wav"

    fun getFileCreateTime(filePath: String) : Triple<Int, Int, Int>{
        val folder = File(filePath)
        val fileCreateTime = folder.lastModified()
        val date = Date(fileCreateTime)
        val format = SimpleDateFormat("yyyy-MM-dd")
        val yearMonthDay = format.format(date).split("-")
        return Triple(yearMonthDay[0].toInt(), yearMonthDay[1].toInt(), yearMonthDay[2].toInt())
    }

    fun createDirectory(path: String, fileDirName: String): FileBean{
        val fileBean = FileBean()
        val file = File(path + "/" + fileDirName)
        fileBean.filePath = "-1"
        if (!file.exists()){
            val mkdirs = file.mkdirs()
            if (mkdirs){
                if (file.isDirectory){
                    fileBean.fileName = file.name
                    fileBean.filePath = file.path
                    fileBean.fileSize = file.length()
                    fileBean.fileType = getFileType(file)
                    fileBean.isDir = true
                }
            }
        }

        return fileBean
    }


    @SuppressLint("Range")
    fun scanFiles(context: Context, uri: Uri, minSize: Long) : ArrayList<FileBean>{
        var filesItemBean : FileBean
        var fileListItemBean = ArrayList<FileBean>()
        val projection = arrayOf(
            MediaStore.Files.FileColumns._ID,
            MediaStore.Files.FileColumns.DISPLAY_NAME,
            MediaStore.Files.FileColumns.SIZE
        )

        val cursor = context.contentResolver.query(uri, projection,null,null,null)
        if (cursor != null && cursor.moveToFirst()){
            do {
                val fileSize = cursor.getLong(cursor.getColumnIndex(MediaStore.Files.FileColumns.SIZE))
                if (fileSize > minSize){
                    filesItemBean = FileBean()
                    filesItemBean.fileName = cursor.getString(cursor.getColumnIndex(MediaStore.Files.FileColumns.DISPLAY_NAME))
                    filesItemBean.fileSize = fileSize
                    filesItemBean.filePath = cursor.getString(cursor.getColumnIndex(MediaStore.Files.FileColumns.RELATIVE_PATH))
                    filesItemBean.isDir = false
                    filesItemBean.fileType = getFileType(File(filesItemBean.filePath))

                    fileListItemBean.add(filesItemBean)
                }

            }while (cursor.moveToNext())
            cursor.close()
        }

        return fileListItemBean

    }

    @SuppressLint("Range")
    fun sanRecursive(context: Context, uri: Uri, minSize: Long): ArrayList<FileBean>{
        var filesItemBeanList = ArrayList<FileBean>()
        filesItemBeanList.addAll(scanFiles(context, uri, minSize))

        val selection = MediaStore.Files.FileColumns.MEDIA_TYPE + "=" +
                MediaStore.Files.FileColumns.MEDIA_TYPE_NONE
        val sortOrder = MediaStore.Files.FileColumns.DATE_MODIFIED
        val cursor = context.contentResolver.query(uri,null, selection,null, sortOrder)
        if (cursor != null && cursor.moveToFirst()){
            do {
                val fileId = cursor.getLong(cursor.getColumnIndex(MediaStore.Files.FileColumns._ID))
                val chiIdUri = Uri.withAppendedPath(uri,""+ fileId)
                filesItemBeanList.addAll(scanFiles(context,chiIdUri, minSize))

            }while (cursor.moveToNext())
            cursor.close()
        }
        return filesItemBeanList
    }

    fun getAllFilesAndDirectories(context: Context): ArrayList<FileBean>{
        var fileList = ArrayList<FileBean>()
//        val internalStorageDir = context.filesDir
        val internalStorageDir = File(EXTERNAL_STORAGE)
        if (internalStorageDir != null && internalStorageDir.exists()){
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                traverseDirectory(internalStorageDir, fileList)
            }
        }

        return fileList
    }

    fun traverseDirectory(directory: File, fileList:ArrayList<FileBean>){
        val files = directory.listFiles()

        if (files!=null){
            for (file: File in files){
                val fileBean: FileBean = FileBean()
                fileBean.fileName = file.name
                fileBean.filePath = file.path
                fileBean.isDir = file.isDirectory
//                val type = Files.probeContentType(Paths.get(file.path))
                if (file.isDirectory){
                    val children = ArrayList<FileBean>()
//                    traverseDirectory(file, children)
                    fileBean.childList = children
                    fileBean.fileType = "dir"
                }else{
                    fileBean.fileType = getFileType(file)
                    fileBean.fileSize = file.length()
                }
                fileList.add(fileBean)
            }
        }
    }

    fun getFileList(directory: File) : ArrayList<FileBean>{
        val fileBeans = ArrayList<FileBean>()
//        val directory = Environment.getExternalStorageDirectory()
        val files = directory.listFiles()
        for (file in files!!){
            if (!file.isHidden && !file.name.startsWith(".") && file.name != ".face") {
                val fileBean = FileBean()
                fileBean.fileName = file.name
                fileBean.filePath = file.path
                fileBean.isDir = file.isDirectory
//                val type = Files.probeContentType(Paths.get(file.path))
                if (file.isDirectory){
                    val children = ArrayList<FileBean>()
                    traverseDirectory(file, children)
                    fileBean.childList = children
                    fileBean.fileType = "dir"
                }else{
                    fileBean.fileType = getFileType(file)
                    fileBean.fileSize = file.length()
                }
                Log.e("yanglin", "getFileList: childList.size = ${fileBean.childList.size}", )
                fileBeans.add(fileBean)
            }
        }
        return fileBeans
    }

    fun getFileType(file: File): String{
        val fileName = file.name
        val indexOf = fileName.lastIndexOf(".")
        if (indexOf != -1 && indexOf < fileName.length -1){
            return fileName.substring(indexOf + 1)
        }else{
            return "notType"
        }
    }

    fun fileListSort(fileList: ArrayList<FileBean>): ArrayList<FileBean>{
        fileList.sortWith(Comparator { fileBean1, fileBean2 ->
            if (File(fileBean1.filePath).isDirectory && !File(fileBean2.filePath).isDirectory) {
                -1
            } else if (!File(fileBean1.filePath).isDirectory && File(fileBean2.filePath).isDirectory) {
                1
            } else {
                fileBean1.fileName.compareTo(fileBean2.fileName)
            }
        })
        return fileList
    }
    /**
     * 查询大于10M的文件
     * ***/
    fun search10MFiles(context: Context, sizeInByte: Int): ArrayList<FileBean>{
        val fileBeans = ArrayList<FileBean>()
        val projection = arrayOf(
            MediaStore.Files.FileColumns.DATA,
            MediaStore.Files.FileColumns.SIZE
        )

        val selection = "${MediaStore.Files.FileColumns.SIZE} > ?"
        val selectionArgs = arrayOf(sizeInByte.toString())

        context.contentResolver.query(
            MediaStore.Files.getContentUri("external"),
            projection,
            selection,
            selectionArgs,
            null
        )?.use { cursor ->
            val dataColumnIndex = cursor.getColumnIndex(MediaStore.Files.FileColumns.DATA)

            while (cursor.moveToNext()) {
                val filePath = cursor.getString(dataColumnIndex)
                val fileBean = FileBean()
                val file = File(filePath)
                fileBean.fileName = file.name
                fileBean.filePath = file.path
                fileBean.fileSize = file.length()
                fileBean.fileType = getFileType(file)
                fileBean.isDir = false
                fileBeans.add(fileBean)
            }
        }
        return fileBeans
    }

    fun renameFile(oldPath: String, newName: String): Boolean {
        val oldFile = File(oldPath)
        val parentDir = oldFile.parentFile // 获取文件的父目录
        val newFile = File(parentDir, newName) // 构建新的文件路径
        return oldFile.renameTo(newFile)
    }

    fun deleteFiles(filePaths: List<String>): Boolean {
        var allDeleted = true
        for (filePath in filePaths) {
            val file = File(filePath)
            val deleted = file.delete()
            if (!deleted) {
                // 删除失败
                allDeleted = false
            }
        }
        return allDeleted
    }

    fun moveFile(path: String, destinationPath: String) : Boolean{
        val file = File(path)
        val destinationFile = File(destinationPath)
        Log.e("yanglin", "moveFile: filePath = ${path}, currentPath = $destinationPath", )
        return file.renameTo(destinationFile)
    }

    fun copyFile(path: String, destinationPath: String): Boolean{
        return try {
            File(path).inputStream().use { input->
                File(destinationPath).outputStream().use { output->
                    input.copyTo(output)
                }
            }
            true
        }catch (e: IOException){
            e.printStackTrace()
            false
        }
    }
    fun scanEmptyFiles(filePath: String, fileList: ArrayList<FileBean>){
        val files = File(filePath).listFiles() // 获取当前目录下的所有文件和文件夹
        if (files != null) {
            for (file in files) {
                if (file.isDirectory && file.listFiles()?.isEmpty() == true) { // 如果是文件夹，则递归搜索
                    val fileBean: FileBean = FileBean()
                    fileBean.fileName = file.name
                    fileBean.filePath = file.path
                    fileBean.fileSize = file.length()
                    fileBean.fileType = "dir"
                    fileBean.isDir = true
                    fileList.add(fileBean)

                }else if (file.isDirectory){
                    scanEmptyFiles(file.path,fileList)
                }
            }
        }
    }


    fun dpToPx(dp: Int, context: Context): Int{
        return TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP,
            dp.toFloat(),
            context.resources.displayMetrics
        ).toInt()
    }

    @SuppressLint("Recycle")
    fun getMediaData(context: Context): ArrayList<FileBean>{
        val fileBeans = ArrayList<FileBean>()
        val projection = arrayOf(MediaStore.Images.Media.DATA)
        val cursor = context.contentResolver.query(
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
            projection,
            null, null, null
        )

        cursor?.let {
            val indexOrThrow = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
            while (cursor.moveToNext()){
                val imagePath = cursor.getString(indexOrThrow)
                val bitmap = BitmapFactory.decodeFile(imagePath)
                val file = File(imagePath)

                val fileBean = FileBean()
                fileBean.fileBitmap = bitmap
                fileBean.fileName = file.name
                fileBean.filePath = imagePath
                fileBean.fileType = getFileType(file)
                Log.e("yanglin", "getFileList: childList.size = ${imagePath}", )
                fileBeans.add(fileBean)
            }
        }
        return fileBeans
    }

    fun getTypeFiles(types: Array<String>, fileBeans: ArrayList<FileBean>){

        MediaStore.Files()
        val externalStorageDir = Environment.getExternalStorageDirectory()
        externalStorageDir.listFiles()?.forEach {
            if (it.isDirectory){
                getTypeFiles(types, fileBeans)
            }else{
                val fileBean = FileBean()
                for (type in types){
                    if (type.contains(getFileType(it))){

                        fileBean.fileName = it.name
                        fileBean.filePath = it.path
                        fileBean.fileSize = it.length()
                        fileBean.fileType = type
                        fileBean.isDir = false
                        fileBeans.add(fileBean)
                        break
                    }
                }
            }
        }
    }

    @SuppressLint("Range")
    fun getMediaFiles(context: Context, fileType: String, limit: Int): ArrayList<FileBean> {
        val fileBeans = ArrayList<FileBean>()
        val projection = arrayOf(MediaStore.Images.Media.DATA)
        var contentUri : Uri
        if (fileType.contains("image")){
            contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
        }else if (fileType.contains("video")){
            contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
        }else if (fileType.contains("audio")){
            contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
        }else{
            contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
        }
        val cursor = context.contentResolver.query(
            contentUri,
            projection,
            null,
            null,
            null
        )
        cursor?.use {
            var count = 0
            while (it.moveToNext()) {
                if (count < limit){
                    val imagePath = it.getString(it.getColumnIndex(MediaStore.Images.Media.DATA))
//                images.add(imagePath)
                    val fileBean = FileBean()
                    val file = File(imagePath)
                    fileBean.fileName = file.name
                    fileBean.filePath = file.path
                    fileBean.fileSize = file.length()
                    fileBean.fileType = getFileType(file)
                    fileBean.isDir = false
                    fileBean.drawable = if (fileType.contains("image")) BitmapDrawable(context.resources, BitmapFactory.decodeFile(file.path)) else null
                    fileBeans.add(fileBean)
                }
                count ++
            }
            cursor.close()
        }

        return fileBeans
    }

    fun getFileType(mimeType: String, context: Context): ArrayList<FileBean>{
        val fileBeans: ArrayList<FileBean> = ArrayList()
        val projection = arrayOf(
            MediaStore.Files.FileColumns.DATA,
            MediaStore.Files.FileColumns.MIME_TYPE
        )

        val selection = "${MediaStore.Files.FileColumns.MIME_TYPE} = ?"
        val selectionArgs = arrayOf(mimeType)

        context.contentResolver.query(
            MediaStore.Files.getContentUri("external"),
            projection,
            selection,
            selectionArgs,
            null
        )?.use { cursor ->
            val dataColumnIndex = cursor.getColumnIndex(MediaStore.Files.FileColumns.DATA)
            while (cursor.moveToNext()) {
                val filePath = cursor.getString(dataColumnIndex)
                val fileBean = FileBean()
                val file = File(filePath)
                fileBean.fileName = file.name
                fileBean.filePath = file.path
                fileBean.fileSize = file.length()
                fileBean.fileType = getFileType(file)
                fileBean.isDir = false
                fileBeans.add(fileBean)
            }
            cursor.close()
        }

        return fileBeans
    }


}