package com.gh.gamecenter.video.upload

import android.annotation.SuppressLint
import com.alibaba.sdk.android.oss.common.OSSLog
import com.gh.gamecenter.core.utils.MD5Utils
import com.gh.gamecenter.common.utils.tryCatchInRelease
import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.common.entity.OssEntity
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.gamecenter.room.AppDatabase
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import java.io.File
import java.util.*

object UploadManager : OnUploadListener {

    private val mUploadThreadMap = Collections.synchronizedMap(HashMap<String, UploadThread>())
    private val mUploadListenerMap = Collections.synchronizedMap(HashMap<String, OnUploadListener>())

    private val mUploadDao = AppDatabase.getInstance().uploadDao()

    init {
        if (BuildConfig.DEBUG) OSSLog.enableLog()
    }

    override fun onProgressChanged(uploadFilePath: String, currentSize: Long, totalSize: Long, speed: Long) {
        mUploadListenerMap[uploadFilePath]?.onProgressChanged(uploadFilePath, currentSize, totalSize, speed)
    }

    override fun onUploadSuccess(uploadFilePath: String, url: String) {
        val entity = mUploadDao.getUploadByFilePath(uploadFilePath)
        if (entity != null) {
            entity.success = true
            tryCatchInRelease { mUploadDao.addUpload(entity) }
        }
        mUploadListenerMap[uploadFilePath]?.onUploadSuccess(uploadFilePath, url)
        mUploadListenerMap.remove(uploadFilePath)
        mUploadThreadMap.remove(uploadFilePath)
    }

    override fun onUploadFailure(uploadFilePath: String, errorMsg: String) {
        mUploadListenerMap[uploadFilePath]?.onUploadFailure(uploadFilePath, errorMsg)
        mUploadListenerMap.remove(uploadFilePath)
        mUploadThreadMap.remove(uploadFilePath)
    }

    @SuppressLint("CheckResult")
    fun createUploadTask(uploadFilePath: String, uploadListener: OnUploadListener) {
        mUploadListenerMap[uploadFilePath] = uploadListener

        val fileMD5 = MD5Utils.calculateMD5(File(uploadFilePath))
        val uploadEntity = mUploadDao.getUploadByFilePath(uploadFilePath)

        if (uploadEntity?.success == true && fileMD5 == uploadEntity.fileMD5) {
            onUploadSuccess(uploadFilePath, uploadEntity.domain + uploadEntity.key)
            return
        }

        if (mUploadThreadMap[uploadFilePath]?.isAlive == true) return

        RetrofitManager.getInstance()
            .api
            .ossUpdateConfig
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : BiResponse<OssEntity>() {

                override fun onSuccess(data: OssEntity) {
                    data.uploadFilePath = uploadFilePath
                    if (uploadEntity != null) {
                        data.domain = uploadEntity.domain
                        data.key = uploadEntity.key
                    } else {
                        tryCatchInRelease {
                            mUploadDao.addUpload(
                                UploadEntity(
                                    uploadFilePath,
                                    fileMD5,
                                    data.domain,
                                    data.key,
                                    false
                                )
                            )
                        }
                    }

                    val uploadThread = UploadThread(data, this@UploadManager)
                    uploadThread.start()
                    mUploadThreadMap[uploadFilePath] = uploadThread
                }

                override fun onFailure(exception: Exception) {
                    onUploadFailure(uploadFilePath, "get oss config failure : " + exception.message)
                }
            })
    }

    fun isUploading(uploadFilePath: String): Boolean {
        return mUploadThreadMap[uploadFilePath]?.isAlive == true
    }

    fun cancelTask(uploadFilePath: String) {
        mUploadListenerMap.remove(uploadFilePath)
        val uploadThread = mUploadThreadMap[uploadFilePath]
        uploadThread?.cancel()
        mUploadThreadMap.remove(uploadFilePath)
    }

    fun deleteUploadData(filePath: String?) {
        filePath?.let {
            mUploadDao.deleteUploadByPath(it)
        }
    }
}
