package com.gh.gamecenter.common.utils

import android.annotation.SuppressLint
import android.graphics.BitmapFactory
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.retrofit.FileRequestBody
import com.gh.gamecenter.common.retrofit.RetrofitCallback
import com.gh.gamecenter.common.retrofit.RetrofitManager
import io.reactivex.Observable
import io.reactivex.ObservableOnSubscribe
import io.reactivex.Observer
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import okhttp3.MultipartBody
import okhttp3.ResponseBody
import org.json.JSONObject
import java.io.File
import java.net.URLEncoder
import java.util.*

object UploadImageUtils {

    enum class UploadType {
        community_article,
        question,
        answer,
        suggestion,
        icon,
        poster,
        game_upload,
        user_background,
        id_photo,
        comment,
        game_list_poster
    }

    // 不处理图片,只是单纯的上传
    fun uploadImage(type: UploadType, imgPath: String, listener: OnUploadImageListener): Disposable {
        return Single.just(imgPath)
            .subscribeOn(Schedulers.computation())
            .flatMap {
                val compressFile = File(imgPath) // compress
                val requestBody =
                    FileRequestBody<ResponseBody>(compressFile, object : RetrofitCallback<ResponseBody>() {
                        override fun onProgress(total: Long, progress: Long) {
                            listener.onProgress(total, progress)
                        }
                    })
                val part = MultipartBody.Part.createFormData("Filedata", getFileName(compressFile), requestBody)

                return@flatMap RetrofitManager.getInstance().uploadApi.uploadImage(part, type.name)
            }
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : BiResponse<ResponseBody>() {
                override fun onSuccess(data: ResponseBody) {
                    val string = data.string()
                    if (!string.isNullOrEmpty()) {
                        val url = JSONObject(string).getString("url")
                        if (!url.isNullOrEmpty()) {
                            listener.onSuccess(url)
                            return
                        }
                    }
                    onFailure(IllegalAccessException("HeHe"))
                }

                override fun onFailure(exception: Exception) {
                    listener.onError(exception)
                }
            })
    }

    // 社区图片上传　后续统一其他
    fun compressAndUploadImage(
        type: UploadType,
        imgPath: String,
        compressGif: Boolean,
        listener: OnUploadImageListener
    ): Disposable {
        return Single.just(imgPath)
            .subscribeOn(Schedulers.computation())
            .flatMap {
                val compressFile = compressImage(it, compressGif) // compress
                val requestBody =
                    FileRequestBody<ResponseBody>(compressFile, object : RetrofitCallback<ResponseBody>() {
                        override fun onProgress(total: Long, progress: Long) {
                            listener.onProgress(total, progress)
                        }
                    })
                val part = MultipartBody.Part.createFormData("Filedata", getFileName(compressFile), requestBody)

                return@flatMap RetrofitManager.getInstance().uploadApi.uploadImage(part, type.name)
            }
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : BiResponse<ResponseBody>() {
                override fun onSuccess(data: ResponseBody) {
                    val string = data.string()
                    if (!string.isNullOrEmpty()) {
                        val url = JSONObject(string).getString("url")
                        if (!url.isNullOrEmpty()) {
                            listener.onSuccess(url)
                            return
                        }
                    }
                    onFailure(IllegalAccessException("HeHe"))
                }

                override fun onFailure(exception: Exception) {
                    listener.onError(exception)
                }
            })
    }

    @SuppressLint("CheckResult")
    fun compressAndUploadImageList(
        type: UploadType,
        imgs: List<String>,
        compressGif: Boolean,
        listener: OnUploadImageListListener
    ): Disposable? {
        var subscription: Disposable? = null
        val postImageList = LinkedHashMap<String, String>()
        val errorMap = HashMap<String, Exception>()

        Observable.create(ObservableOnSubscribe<Map<String, String>> {
            val compressList = compressImageList(imgs, compressGif)
            listener.onCompressSuccess(compressList.map { file -> file.absolutePath }.toList())
            var listTotal = 0L // 总大小
            var listProgress = 0L // 已上传的大小
            for (img in compressList) {
                listTotal += img.length()
            }
            for (img in compressList) {
                if (subscription?.isDisposed == true) return@ObservableOnSubscribe
                val requestBody = FileRequestBody<ResponseBody>(img, object : RetrofitCallback<ResponseBody>() {
                    override fun onProgress(total: Long, progress: Long) {
                        if (subscription?.isDisposed != true) {
                            listener.onProgress(listTotal, listProgress + progress)
                        }
                    }
                })
                val part = MultipartBody.Part.createFormData("Filedata", getFileName(img), requestBody)
                RetrofitManager.getInstance()
                    .uploadApi.uploadImage(part, type.name)
                    .subscribe(object : BiResponse<ResponseBody>() {
                        override fun onSuccess(data: ResponseBody) {
                            if (subscription?.isDisposed == true) return
                            val string = data.string()
                            if (!string.isNullOrEmpty()) {
                                val url = JSONObject(string).getString("url")
                                if (!url.isNullOrEmpty()) {
                                    val map = LinkedHashMap<String, String>()
                                    map[img.path] = url
                                    it.onNext(map)
                                    return
                                }
                            }
                            onFailure(IllegalAccessException("HeHe"))
                        }


                        override fun onFailure(exception: Exception) {
                            // 若遇到错误且 subscription?.isDisposed 为 true 时会抛出 io.reactivex.exceptions.UndeliverableException 异常
                            // if (subscription?.isDisposed == true) return
                            // it.onError(exception) // fuck
                            // it.onNext(Collections.emptyMap())
                            errorMap[img.path] = exception
                        }
                    })
                listProgress += img.length()
            }
            it.onComplete()
        })
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Observer<Map<String, String>?> {
                override fun onSubscribe(d: Disposable) {
                    subscription = d
                }

                override fun onComplete() {
                    if (postImageList.size == 0) {
                        listener.onError(errorMap)
                    } else {
                        listener.onSuccess(postImageList, errorMap)
                    }
                }

                override fun onNext(t: Map<String, String>) {
                    if (t.isNotEmpty()) {
                        listener.onSingleSuccess(t)
                        postImageList.putAll(t)
                    }
                }

                override fun onError(ignore: Throwable) {

                }
            })
        return subscription
    }

    /**
     * 上传图片,每成功一个就回调
     */
    @SuppressLint("CheckResult")
    fun uploadImageListOneByOne(
        type: UploadType,
        imgs: List<String>,
        compressGif: Boolean,
        listener: OnUploadImageListCountListener
    ): Disposable? {
        var subscription: Disposable? = null
        Observable.create(ObservableOnSubscribe<Map<String, String>> {
            //val compressList = compressImageList(imgs, compressGif)

            for (img in imgs) {
                if (subscription?.isDisposed == true) return@ObservableOnSubscribe
                val file = File(img)
                val requestBody = FileRequestBody(file, object : RetrofitCallback<ResponseBody>() {
                    override fun onProgress(total: Long, progress: Long) {

                    }
                })
                val part = MultipartBody.Part.createFormData("Filedata", getFileName(file), requestBody)
                RetrofitManager.getInstance()
                    .uploadApi.uploadImage(part, type.name)
                    .subscribe(object : BiResponse<ResponseBody>() {
                        override fun onSuccess(data: ResponseBody) {
                            if (subscription?.isDisposed == true) return
                            val string = data.string()
                            if (!string.isNullOrEmpty()) {
                                val url = JSONObject(string).getString("url")
                                if (!url.isNullOrEmpty()) {
                                    val map = LinkedHashMap<String, String>()
                                    map[file.path] = url
                                    it.onNext(map)
                                    return
                                }
                            }
                            onFailure(IllegalAccessException("HeHe"))
                        }

                        override fun onFailure(exception: Exception) {
                            // 若遇到错误且 subscription?.isDisposed 为 true 时会抛出 io.reactivex.exceptions.UndeliverableException 异常
                            // if (subscription?.isDisposed == true) return
                            // it.onError(exception) // fuck
                            it.onNext(Collections.emptyMap())
                        }
                    })
            }
            it.onComplete()
        })
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Observer<Map<String, String>?> {
                override fun onSubscribe(d: Disposable) {
                    subscription = d
                }

                override fun onComplete() {
                    listener.onFinish()
                }

                override fun onNext(t: Map<String, String>) {
                    if (t.isNotEmpty()) {
                        listener.onSuccess(t)
                    }
                }

                override fun onError(e: Throwable) {
                    listener.onError()
                    e.printStackTrace()
                }
            })
        return subscription
    }

    // 同步调用->避免在主线程调用以免阻塞主线程
    private fun compressImageList(imgs: List<String>, compressGif: Boolean): List<File> {
        val compressList: MutableList<File> = ArrayList()
        for (img in imgs) {
            compressList.add(CompressImageUtils.compressImageAndSaveToFile(File(img), compressGif))
        }
        return compressList
    }

    // 同步调用->避免在主线程调用以免阻塞主线程
    private fun compressImage(imgPath: String, compressGif: Boolean): File {
        return CompressImageUtils.compressImageAndSaveToFile(File(imgPath), compressGif)
    }

    // 防止GIF图片文件后缀不是GIF，这个FileName只是告诉服务端后缀格式，没有其他用处
    fun getFileName(file: File): String {
        val options = BitmapFactory.Options()
        options.inJustDecodeBounds = true
        BitmapFactory.decodeFile(file.absolutePath, options)
        if (options.outMimeType != null && options.outMimeType.contains("gif") && !file.name.toLowerCase()
                .contains(".gif".toLowerCase())
        ) {
            return System.currentTimeMillis().toString() + ".gif"
        }
        return URLEncoder.encode(file.name, "utf-8")
    }

    interface OnUploadImageListener {
        fun onSuccess(imageUrl: String)
        fun onError(e: Throwable?)
        fun onProgress(total: Long, progress: Long)
    }

    interface OnUploadImageListListener {
        fun onSuccess(
            imageUrlMap: LinkedHashMap<String, String>,
            errorMap: Map<String, Exception>
        ) // key:sourceImage value:compressImage

        fun onSingleSuccess(imageUrlMap: Map<String, String>)
        fun onCompressSuccess(imageUrls: List<String>) {}
        fun onError(errorMap: Map<String, Exception>) // 全部上传失败时回调
        fun onProgress(total: Long, progress: Long)
    }

    interface OnUploadImageListCountListener {
        fun onSuccess(map: Map<String, String>)//上传成功一个回调
        fun onFinish()//全部上传成功回调
        fun onError() // 全部上传失败时回调
    }
}