package com.convenient.android.common.media.scan

import android.os.Environment
import com.convenient.android.common.extension.listFilesInDirWithFilter
import com.convenient.android.common.extension.toFile
import com.convenient.android.common.media.MediaBean
import com.convenient.android.common.media.basic.Query
import com.convenient.android.common.media.config.MediaQueryConfig
import com.convenient.android.common.media.config.MediaSortOrder
import com.convenient.android.common.media.config.MediaSortType
import com.convenient.android.common.media.config.SortUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.File

/**
 * @classname:
 * @author: LiuXiaoLong
 * @date: 2022/8/2
 * description: 通过File 来获取文件下的所有文件
 */
object FileStore : Query {


    override suspend fun query(dir: String, config: MediaQueryConfig.() -> Unit): List<MediaBean> {
        return query(dir, config = MediaQueryConfig().also(config))
    }

    /**
     * 列出指定文件目录的文件
     * @param dir 要获取的文件目录
     * @param config 查询时的配置，指定排序等
     *
     */
    override suspend fun query(dir: String, config: MediaQueryConfig): List<MediaBean> = withContext(Dispatchers.IO){
        val dirFile = if (dir.isEmpty()) Environment.getExternalStorageDirectory() else "${dir}/".toFile()


        val f = dirFile?.listFiles()
        val files: List<File> = dirFile?.listFilesInDirWithFilter(recursively = config.recursively, accept = {

            if (it.absolutePath.equals(dir)) {
                return@listFilesInDirWithFilter false
            }

            if (it.isDirectory && config.includeFolder.not()) {
                //移除文件夹
                return@listFilesInDirWithFilter false
            }

            //要忽略的子文件或文件夹与当前相同，返回false
            if (config.ignoreChildFiles.contains(it) || config.ignoreChildFiles.any { child ->
                    it.startsWith(child)
                }) {
                return@listFilesInDirWithFilter false
            }
            //如果没有指定需要的文件格式，则全部返回
            if (config.supportMimeTypes.isEmpty()) {
                true
            } else {
                config.supportMimeTypes.contains(it.extension.lowercase())
            }
        }) ?: emptyList()

        //对文件进行排序
        sortList(
            order = config.order,
            sortType = config.sortType,
            data = files,
            sortByDateSelector = { it.lastModified() },
            sortByNameSelector = { it.name },
            sortBySizeSelector = { it.length() },
        ).sortedBy { it.isFile }
            .map {
                MediaBean(
                    mediaPath = it.absolutePath,
                    name = it.name,
                    extension = it.extension,
                    isFile = it.isFile,
                    lastModified = if (it.isFile) it.lastModified() else 0L,
                    length = it.length(),
                    parentPath = it.parent ?: ""
                )
            }.toList()

    }


    /**
     * 集合排序
     * @param order 升序、降序
     * @param sortType 根据指定的枚举类型进行排序
     * @param data 要进行排序的集合
     * @param sortByNameSelector 根据名称排序 传入对应字段
     * @param sortByDateSelector 传入时间字段
     * @param sortBySizeSelector 根据大小排序， 传入记录大小的字段
     * @see MediaSortOrder.DESC
     * @see MediaSortOrder.ASC
     * @see MediaSortType.NAME
     * @see MediaSortType.SIZE
     * @see MediaSortType.DATE
     */
    private fun <T, R : Comparable<R>, S : Comparable<S>> sortList(
        order: MediaSortOrder,
        sortType: MediaSortType,
        data: List<T>,
        sortByNameSelector: (T) -> S?,
        sortByDateSelector: (T) -> R?,
        sortBySizeSelector: (T) -> R?,
    ): Sequence<T> {
        return when (sortType) {
            MediaSortType.DATE -> SortUtils.sort(order, data, sortByDateSelector)
            MediaSortType.NAME -> SortUtils.sort(order, data, sortByNameSelector)
            MediaSortType.SIZE -> SortUtils.sort(order, data, sortBySizeSelector)
        }
    }

}


