package com.khmer9.yuki.app

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.khmer9.yuki.base.BaseViewModel
import com.khmer9.yuki.remote.ReportBettingRequest
import com.khmer9.yuki.remote.ReportDepositRequest
import com.khmer9.yuki.remote.ReportResultRequest
import com.khmer9.yuki.remote.ReportWithdrawRequest
import com.khmer9.yuki.remote.service.ApiService
import com.khmer9.yuki.remote.service.ConnectivityStates
import com.khmer9.yuki.remote.service.EventListener
import com.khmer9.yuki.screen.main.ResultMainState
import com.khmer9.yuki.screen.report.ReportViewState
import com.khmer9.yuki.screen.result.ResultViewState
import com.khmer9.yuki.util.PrefHelper
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import java.util.concurrent.TimeUnit

class ShareViewModel(
    private val apiService: ApiService,
    private val prefHelper: PrefHelper,
    //private val socketService: SocketService
) : BaseViewModel(), EventListener {

    //Socket Connection Live Data
    private val connectivityStateLD = MutableLiveData<Int>()
    val getConnectivityStates: LiveData<Int> get() = connectivityStateLD

    //MainScreen and Create Betting Screen
    private val shareState = MutableLiveData(ShareViewState())
    val getShareState: LiveData<ShareViewState> = shareState

    //---------------------------------- New Live Data
    //Main Module Data
    private val mainModuleState = MutableLiveData(ResultMainState())
    val getMainModuleState: LiveData<ResultMainState> = mainModuleState

    //Result Screen Live Data
    private val resultState = MutableLiveData<ResultViewState>(ResultViewState())
    val getResultState: LiveData<ResultViewState> = resultState

    //Report Screen Live Data
    private val reportState = MutableLiveData<ReportViewState>(ReportViewState())
    val getReportState: LiveData<ReportViewState> = reportState

    //-----------------------------------------------------Report statement----------------------------------------------------------
    fun remoteReportBettingStatement(reportBettingRequest: ReportBettingRequest? = null) {
        if (reportState.value!!.isProgress) return
        reportState.value = prevReport().copy(isProgress = true)

        var request = ReportBettingRequest("", "", 20, 1)

        if (reportBettingRequest == null) {
            request = ReportBettingRequest("", "", 20, 1)
        } else {
            request = reportBettingRequest
        }

        disposables.add(
            apiService.remoteBettingScreen(request)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({ response ->
                    if (response.resultCode == "1") {
                        response.data?.let {
                            reportState.value = prevReport().copy(
                                isProgress = false,
                                statementList = it.statementList,
                                statementListTurnOver = it.turnOver,
                                statementListAmountWinLose = it.amountWinLose,
                                error = null
                            )
                        }
                    } else {
                        reportState.value = prevReport().copy(isProgress = false, error = "[${response.message.description}]")
                    }
                }, {
                    val message: String = "ប្រតិបត្តិការមិនជោគជ័យ\n" + it.getErrorCode()
                    reportState.value = prevReport().copy(isProgress = false, error = message)
                })
        )
    }

    fun remoteReportWithdrawStatement(reportWithdrawRequest: ReportWithdrawRequest? = null) {
        if (reportState.value!!.isProgress) return

        var request = ReportWithdrawRequest("", "", 20, 1)

        if (reportWithdrawRequest == null) {
            request = ReportWithdrawRequest("", "", 20, 1)
        } else {
            request = reportWithdrawRequest
        }

        reportState.value = prevReport().copy(isProgress = true)
        disposables.add(
            apiService.remoteWithdrawScreen(request)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({ response ->
                    if (response.resultCode == "1") {
                        response.data?.let {
                            reportState.value = prevReport().copy(
                                isProgress = false,
                                statementWithdrawList = it.statementWithdrawList,
                                statementWithdrawTotalAmount = it.totalAmount,
                                error = null
                            )
                        }
                    } else {
                        reportState.value = prevReport().copy(isProgress = false, error = "[${response.message.description}]")
                    }
                }, {
                    val message: String = "ប្រតិបត្តិការមិនជោគជ័យ\n" + it.getErrorCode()
                    reportState.value = prevReport().copy(isProgress = false, error = message)
                })
        )
    }

    fun remoteReportDepositStatement(reportDepositRequest: ReportDepositRequest? = null) {
        if (reportState.value!!.isProgress) return

        var request = ReportDepositRequest("", "", 20, 1)

        if (reportDepositRequest == null) {
            request = ReportDepositRequest("", "", 20, 1)
        } else {
            request = reportDepositRequest
        }

        reportState.value = prevReport().copy(isProgress = true)
        disposables.add(
            apiService.remoteDepositScreen(request)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({ response ->
                    if (response.resultCode == "1") {
                        response.data?.let {
                            reportState.value = prevReport().copy(
                                isProgress = false,
                                statementDepositList = it.statementDepositList,
                                statementDepositTotalAmount = it.totalAmount,
                                error = null
                            )
                        }
                    } else {
                        reportState.value = prevReport().copy(isProgress = false, error = "[${response.message.description}]")
                    }
                }, {
                    val message: String = "ប្រតិបត្តិការមិនជោគជ័យ\n" + it.getErrorCode()
                    reportState.value = prevReport().copy(isProgress = false, error = message)
                })
        )
    }

    fun remoteReportResultStatement(reportResultRequest: ReportResultRequest? = null) {
        if (reportState.value!!.isProgress) return

        var request = ReportResultRequest("", "", 20, 1)

        if (reportResultRequest == null) {
            request = ReportResultRequest("", "", 20, 1)
        } else {
            request = reportResultRequest
        }

        reportState.value = prevReport().copy(isProgress = true)
        disposables.add(
            apiService.remoteResultStatementScreen(request)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({ response ->
                    if (response.resultCode == "1") {
                        response.data?.let {
                            reportState.value = prevReport().copy(
                                isProgress = false,
                                statementResultList = it.resultList,
                                error = null
                            )
                        }
                    } else {
                        reportState.value = prevReport().copy(isProgress = false, error = "[${response.message.description}]")
                    }
                }, {
                    val message: String = "ប្រតិបត្តិការមិនជោគជ័យ\n" + it.getErrorCode()
                    reportState.value = prevReport().copy(isProgress = false, error = message)
                })
        )
    }

    //-----------------------------------------------------End Report Statement----------------------------------------------------------

    fun remoteMainModule() {
        if (mainModuleState.value!!.isProgress) return
        mainModuleState.value = prevMainModule().copy(isProgress = true)

        disposables.add(
            apiService.remoteMainModule()
                .timeout(60, TimeUnit.SECONDS)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({ response ->
                    if (response.resultCode == "1") {
                        response.data?.let {
                            val sortedList = it.sortedWith(compareBy { it.order })
                            mainModuleState.value = prevMainModule().copy(
                                isProgress = false,
                                resultList = sortedList,
                                error = null
                            )
                        }
                    } else {
                        mainModuleState.value = prevMainModule().copy(isProgress = false, error = "[${response.message.description}]")
                    }
                }, {
                    val message: String = "ប្រតិបត្តិការមិនជោគជ័យ\n" + it.getErrorCode()
                    mainModuleState.value = prevMainModule().copy(isProgress = false, error = message)
                })
        )
    }

    fun remoteResult() {
        if (resultState.value!!.isProgress) return
        resultState.value = prevResult().copy(isProgress = true)

        disposables.add(
            apiService.remoteResultScreen()
                .timeout(60, TimeUnit.SECONDS)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({ response ->
                    if (response.resultCode == "1") {
                        response.data?.let {
                            val sortedList = it.sortedWith(compareBy { it.no })
                            resultState.value = prevResult().copy(
                                isProgress = false,
                                resultList = sortedList,
                                error = null
                            )
                        }
                    } else {
                        resultState.value = prevResult().copy(isProgress = false, error = "[${response.message.description}]")
                    }
                }, {
                    val message: String = "ប្រតិបត្តិការមិនជោគជ័យ\n" + it.getErrorCode()
                    resultState.value = prevResult().copy(isProgress = false, error = message)
                })
        )
    }

    // Server callbacks
    override fun onConnect() {
        connectivityStateLD.postValue(ConnectivityStates.STATE_CONNECTED)
    }

    override fun onReconnectionTimeout() {
        connectivityStateLD.postValue(ConnectivityStates.STATE_TIMEOUT)
    }

    override fun onConnectionError() {
        connectivityStateLD.postValue(ConnectivityStates.STATE_NOT_CONNECTED)
    }

    override fun onReconnect() {
        connectivityStateLD.postValue(ConnectivityStates.STATE_RECONNECTING)
    }

    override fun onDisconnect() {
        connectivityStateLD.postValue(ConnectivityStates.STATE_DISCONNECTED)
    }

    private val clientNewGameState = MutableLiveData<String>()
    val getClientNewGame: LiveData<String> get() = clientNewGameState
    override fun onClientNewGameListener(data: String?) {
        clientNewGameState.postValue(data)
    }

    private val clientRandomState = MutableLiveData<String>()
    val getClientRandom: LiveData<String> get() = clientRandomState
    override fun onClientRandomListener(data: String?) {
        clientRandomState.postValue(data)
    }

    override fun onClientResetListener(data: String?) {
    }

    private val clientResultState = MutableLiveData<String>()
    val getClientResult: LiveData<String> get() = clientResultState
    override fun onClientResultListener(data: String?) {
        clientResultState.postValue(data)
    }

    override fun onClientUpdateInfoListener(data: String?) {
    }

    private val clientTimeState = MutableLiveData<String>()
    val getClientTime: LiveData<String> get() = clientTimeState
    override fun onClientTimeListener(data: String?) {
        clientTimeState.postValue(data)
    }

    private fun prevMainModule() = mainModuleState.value!!

    private fun prevResult() = resultState.value!!

    private fun prevReport() = reportState.value!!
}