package com.adealink.weparty.effect

import androidx.lifecycle.LiveData
import com.adealink.frame.base.IError
import com.adealink.frame.download.listener.TaskListener
import com.adealink.frame.download.task.Task
import com.adealink.frame.download.task.TaskPriority
import com.adealink.frame.effect.data.EffectAnimType
import com.adealink.frame.log.Log
import com.adealink.frame.mvvm.livedata.OnceMutableLiveData
import com.adealink.frame.mvvm.viewmodel.BaseViewModel
import com.adealink.frame.storage.file.WeFile
import com.adealink.frame.storage.file.getCacheFilePathByUrl
import com.adealink.frame.storageService
import com.adealink.frame.util.md5
import com.adealink.weparty.App
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlin.coroutines.resume

class EffectViewModel : BaseViewModel() {

    fun downloadResources(urls: List<String>, priority: TaskPriority): LiveData<List<WeFile?>> {
        val liveData = OnceMutableLiveData<List<WeFile?>>()
        viewModelScope.launch {
            val resultList = coroutineScope {
                urls.map { url ->
                    async {
                        downloadEffect(url, priority)
                    }
                }.awaitAll()
            }
            liveData.send(resultList)
        }
        return liveData
    }

    fun downloadResource(url: String, priority: TaskPriority): LiveData<WeFile?> {
        val liveData = OnceMutableLiveData<WeFile?>()
        viewModelScope.launch {
            liveData.send(
                downloadEffect(url, priority)
            )
        }
        return liveData
    }

    /**
     * 接入腾讯云特效播放器后按需使用，需传入新旧链接，根据特效特效播放器可用情况下载对应资源
     */
    fun downloadResource(
        oldUrl: String,
        newUrl: String?,
        newAnimType: Int,
        forceOldRes: Boolean = false,
        priority: TaskPriority = TaskPriority.NORMAL
    ): LiveData<EffectSaveResource> {
        val liveData = OnceMutableLiveData<EffectSaveResource>()
        val effectUrl: String
        val effectAnimType: Int
        when (forceOldRes || newUrl.isNullOrEmpty()) {
            true -> {
                effectUrl = oldUrl
                effectAnimType = EffectAnimType.getOldEffectAnimTypeByUrl(oldUrl)
            }

            else -> {
                effectUrl = newUrl
                effectAnimType = newAnimType
            }
        }
        viewModelScope.launch {
            val animType = EffectAnimType.map(effectAnimType)
            if (animType == null) {
                //不支持的动效类型
                liveData.send(EffectSaveResource(null, effectAnimType))
                return@launch
            }
            liveData.send(
                EffectSaveResource(downloadEffect(effectUrl, priority), effectAnimType)
            )
        }
        return liveData
    }

    private suspend fun downloadEffect(url: String, priority: TaskPriority): WeFile? {
        val savePath = getCacheFilePathByUrl(url)
        return suspendCancellableCoroutine { continuation ->
            addDownloadTask(url, savePath, priority,
                { localPath ->
                    if (continuation.isActive) {
                        continuation.resume(
                            localPath
                        )
                    }
                },
                {
                    if (continuation.isActive) {
                        continuation.resume(null)
                    }
                })
        }
    }

    private fun addDownloadTask(
        url: String,
        savePath: String,
        priority: TaskPriority,
        success: ((path: WeFile) -> Unit)? = null,
        failed: ((error: IError) -> Unit)? = null,
    ) {
        Log.d(TAG, "addDownloadTask, url: $url")
        Log.d(TAG, "                 savePath: $savePath")
        val file = storageService.file.createWeFile(savePath)
        if (file.exists()) {
            Log.d(TAG, "addDownloadTask, fileExist, return")
            success?.invoke(file)
            return
        }

        val taskId = url.md5()
        val task = Task(taskId, url, savePath, TaskPriority.getPriority(priority))
        Log.d(
            TAG,
            "addDownloadTask, start download, url:$url, task:$task"
        )
        task.listeners.add(object : TaskListener {

            override fun onFinished(task: Task) {
                super.onFinished(task)
                success?.invoke(file)
                Log.d(
                    TAG,
                    "addDownloadTask, download success, task:$task"
                )
            }

            override fun onError(task: Task, error: IError) {
                super.onError(task, error)
                failed?.invoke(error)
                Log.e(
                    TAG,
                    "addDownloadTask, task:$task, error:$error"
                )
            }
        })
        addDownloadTask(task)
    }

    private fun addDownloadTask(task: Task) {
        App.instance.downloadService.addTask(task)
    }

    companion object {
        private const val TAG = "EffectViewModel"
    }

}