package com.ccwangluo.accelerator.manager

import android.Manifest
import android.app.DownloadManager
import android.content.Context
import android.database.Cursor
import android.net.Uri
import android.os.Environment
import android.webkit.MimeTypeMap
import androidx.lifecycle.lifecycleScope
import com.ccwangluo.accelerator.model.GameInfo
import com.ccwangluo.accelerator.utils.datareport.DataRePortUtils
import com.hjq.toast.ToastUtils
import com.xuexiang.xpage.base.XPageFragment
import com.xuexiang.xutil.system.PermissionUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File

object GameDownLoadManger {

    private var downloadManager: DownloadManager? = null
    private var gameDownloadListener: GameDownloadListener? = null
    fun registerLisener(gameDownloadListener: GameDownloadListener) {
        this.gameDownloadListener = gameDownloadListener
    }

    private val downloadMap = mutableMapOf<Long, GameInfo>()

    fun download(
        activity: XPageFragment,
        gameInfo: GameInfo,
        url: String
    ) {
        if (url.isNullOrBlank()) {
            return
        }
        if (!PermissionUtils.isGranted(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
            ToastUtils.show("下载需要打开存储权限")
            PermissionUtils.permission(Manifest.permission.WRITE_EXTERNAL_STORAGE.toString())
                .rationale {
                    PermissionUtils.openAppSettings()
                }.request()
            return
        }
        var filename = url.split("/").last()
        var file = File(
            activity.context?.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
            filename
        )

        if (file.exists()) {
//            activity.context?.let { DownloadUtils.install(file.absolutePath, it) }
            file.delete()
        }
        downloadManager =
            activity.context?.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
        val request =
            DownloadManager.Request(Uri.parse(url)) //添加下载文件的网络路径

        request.setDestinationInExternalFilesDir(
            activity.context,
            Environment.DIRECTORY_DOWNLOADS,
            filename
        )
        val mimeTypeMap = MimeTypeMap.getSingleton()
        val mimeString =
            mimeTypeMap.getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(url))
        request.setMimeType(mimeString)

        request.setTitle("下载中") //添加在通知栏里显示的标题
//        request.setDescription("下载中") //添加在通知栏里显示的描述

        request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE or DownloadManager.Request.NETWORK_WIFI) //设置下载的网络类型

        request.setVisibleInDownloadsUi(false) //是否显示下载 从Android Q开始会被忽略

        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) //下载中与下载完成后都会在通知中显示| 另外可以选 DownloadManager.Request.VISIBILITY_VISIBLE 仅在下载中时显示在通知中,完成后会自动隐藏

        var downloadId = downloadManager!!.enqueue(request) //加入队列，会返回一个唯一下载id
        downloadMap.put(downloadId, gameInfo)
        gameDownloadListener?.onStart(gameInfo)
        show(activity, downloadId,gameInfo)
    }

    fun show(activity: XPageFragment, downloadId: Long,gameInfo: GameInfo) {
        activity.lifecycleScope.launch(Dispatchers.IO) {
            var progress = 0F
            while (progress < 100F) {
                progress = getDownloadProgress(downloadId)
                delay(1000)
            }
            DataRePortUtils.report("st_pop_dld_result", mapOf("gameid" to gameInfo.id.toString(),"result" to 1))
            withContext(Dispatchers.Main) {
                gameDownloadListener?.onFinish(downloadMap.get(downloadId))
                downloadMap.remove(downloadId)
            }
        }
    }

    fun containGame(gameInfo: GameInfo): Boolean {
        downloadMap.keys.forEach {
            val get = downloadMap.get(it)
            if (get?.id == gameInfo.id) {
                return true
            }
        }
        return false
    }

    fun cancellDownload(gameInfo: GameInfo) {
        try {
            downloadMap.keys.forEach {
                val get = downloadMap.get(it)
                if (get?.id == gameInfo.id) {
                    downloadManager?.remove(it)
                    gameDownloadListener?.onFinish(gameInfo)
                    downloadMap.remove(it)
                    DataRePortUtils.report("st_pop_dld_result", mapOf("gameid" to gameInfo.id.toString(),"result" to 0))
                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    suspend fun getDownloadProgress(downloadId: Long):Float {
        val query = DownloadManager.Query().setFilterById(downloadId)
        downloadManager?.let {
            val c: Cursor = it.query(query)
            if (c != null) {
                try {
                    if (c.moveToFirst()) {
                        var progress = 0F
                        val mDownload_so_far =
                            c.getLong(c.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR))
                        val status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS))
                        val mDownload_all =
                            c.getLong(c.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES))
                        if (mDownload_all != 0L) {
                            progress = (mDownload_so_far.toFloat() / mDownload_all) * 100
                        }
                        val downloadInfo = DownloadInfo(
                            status,
                            progress,
                            0,
                            mDownload_so_far,
                            mDownload_all
                        )
                        withContext(Dispatchers.Main) {
                            gameDownloadListener?.onProgress(
                                downloadMap.get(downloadId),
                                downloadInfo
                            )
                        }
                        return progress
                    }
                } catch (e : Exception){
                    println("progress err ${e}")
                }finally {
                    c.close()
                }
            }
        }
        return 0F
    }

    interface GameDownloadListener {
        fun onStart(gameInfo: GameInfo?)
        fun onFinish(gameInfo: GameInfo?)
        fun onProgress(gameInfo: GameInfo?, downloadInfo: DownloadInfo)
    }

    data class DownloadInfo(
        var status: Int,
        var progress: Float,
        var speed: Long,
        var download_so_far: Long,
        var download_all: Long
    )

}