package com.remax.visualnovel.entity.response.base


import com.google.gson.annotations.SerializedName
import com.remax.visualnovel.app.base.app.CommonApplicationProxy
import com.remax.visualnovel.extension.toast

/**
 * Created by HJW on 2022/10/27
 */
open class Response<T>(
    @SerializedName(value = "content")
    val data: T? = null,
    open val errorCode: String = "",
    open val errorMsg: String = "",
    val status: String = successCode
) {

    companion object {
        const val successCode = "OK"

        /**
         * zip打包的错误error封装
         * new
         */
        inline fun <reified T> createZipFailResponse(vararg data: Response<*>): ApiFailedResponse<T> {
            val failedResponse = ApiFailedResponse<T>()
            for (t in data) {
                if (!t.isApiSuccess) {
                    failedResponse.errorCode = t.errorCode
                    failedResponse.errorMsg = t.errorMsg
                    break
                }
            }
            return failedResponse
        }
    }

    val isOk: Boolean
        get() = status == successCode

    val isApiSuccess: Boolean
        get() =
            this is ApiSuccessResponse || this is ApiEmptyResponse

    /**
     * 将返回结果分为成功和失败2个高阶函数
     *
     * 使用inline修饰，使2个参数可以调用外部函数return
     */
    inline fun transformResult(apiSuccessCallback: ((T?) -> Unit) = {}, apiFailedCallback: ((Response<T>) -> Unit) = {}): Response<T> {
        if (isApiSuccess) {
            apiSuccessCallback.invoke(data)
        } else {
            apiFailedCallback.invoke(this)
        }
        return this
    }
}

inline fun <reified T> Response<T>.parseData(listenerBuilder: (ResultBuilder<T>.() -> Unit), showToast: Boolean = false) {
    val listener = ResultBuilder<T>().also(listenerBuilder)
    when (this) {
        is ApiSuccessResponse -> listener.onSuccess(this.response)
        is ApiEmptyResponse -> listener.onSuccess(null)
        is ApiFailedResponse -> {
            listener.onFailed(this.errorCode, this.errorMsg)
            listener.onFailedWithData(this.data)
            if (showToast) {
                CommonApplicationProxy.application.toast(errorMsg)
            }
        }
    }
    listener.onComplete()
}

class ResultBuilder<T> {
    var onSuccess: (data: T?) -> Unit = {}
    var onFailed: (errorCode: String, errorMsg: String) -> Unit = { _, _ ->

    }
    var onFailedWithData: (errorData: T?) -> Unit = {}
    var onComplete: () -> Unit = {}
}

data class ApiSuccessResponse<T>(val response: T? = null) : Response<T>(data = response)

class ApiEmptyResponse<T> : Response<T>()

data class ApiFailedResponse<T>(override var errorCode: String = "", override var errorMsg: String = "", val errorData: T? = null) :
    Response<T>(data = errorData, errorCode = errorCode, errorMsg = errorMsg)

