package com.casic.common.detector.gd.service

import android.app.Service
import android.content.Intent
import android.os.Handler
import android.os.IBinder
import android.os.Message
import android.util.Base64
import android.util.Log
import android.view.Gravity
import android.widget.Toast
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LifecycleRegistry
import androidx.lifecycle.lifecycleScope
import com.casic.common.detector.gd.base.BaseApplication
import com.casic.common.detector.gd.extensions.convertToGPGGA
import com.casic.common.detector.gd.utils.LocaleConstant
import com.casic.common.detector.gd.utils.NtripAuthorizationCreator
import com.casic.common.detector.gd.utils.RtkLocationTool
import com.casic.common.detector.gd.view.MainActivity
import com.pengxh.kt.lite.extensions.show
import com.pengxh.kt.lite.utils.SaveKeyValues
import com.pengxh.kt.lite.utils.WeakReferenceHandler
import com.pengxh.kt.lite.utils.socket.tcp.OnTcpConnectStateListener
import com.pengxh.kt.lite.utils.socket.tcp.TcpClient
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.io.OutputStream
import java.nio.charset.StandardCharsets


class NtripConnectService : Service(), LifecycleOwner, OnTcpConnectStateListener, Handler.Callback {

    companion object {
        var weakReferenceHandler: WeakReferenceHandler? = null
    }

    private val kTag = "NtripConnectService"
    private val registry = LifecycleRegistry(this)
    private val socketClient by lazy { TcpClient(this) }
    private var outStream: OutputStream? = null

    override fun getLifecycle(): Lifecycle {
        return registry
    }

    override fun onBind(intent: Intent?): IBinder? {
        return null
    }

    override fun handleMessage(msg: Message): Boolean {
        if (msg.what == 2024082201) {
            lifecycleScope.launch(Dispatchers.IO) {
                connectQianXunServer()
            }
        }
        return true
    }

    override fun onCreate() {
        super.onCreate()
        weakReferenceHandler = WeakReferenceHandler(this)

        connectQianXunServer()

        RtkLocationTool.getCurrentLocation(this) {
            val weakHandler = MainActivity.weakReferenceHandler ?: return@getCurrentLocation
            val message = weakHandler.obtainMessage()
            message.what = 2024090301
            message.obj = "${it.longitude},${it.latitude}"
            weakHandler.sendMessage(message)

            if (socketClient.isRunning()) {
                //连接成功就发送千寻请求报文
                val gga = it.convertToGPGGA()
                Log.d(kTag, gga)
                socketClient.sendMessage(gga.toByteArray())
            }
        }
    }

    /**
     * Ntrip服务器需要两步验证：
     * 第一步是connect，
     * 第二步是发送check cmd。
     * 这二步是连续的，要不然服务器就会拒绝，显示一连就失败
     * */
    override fun onConnected() {
        //连接成功就发送千寻请求报文
        val account = SaveKeyValues.getValue(LocaleConstant.ACK, "qxtmcr0087663") as String
        val pwd = SaveKeyValues.getValue(LocaleConstant.ACS, "1f1f9b9") as String

        // base64加密用户名和密码
        val byteArray = "$account:$pwd".toByteArray()
        val base64 = Base64.encodeToString(byteArray, Base64.DEFAULT)

        val msg = NtripAuthorizationCreator()
            .append("GET /RTCM32_GGB HTTP/1.1")
            .append("Host: ${LocaleConstant.QX_RTK_HOST}")
            .append("Ntrip-Version: Ntrip/2.0")
            .append("User-Agent: NTRIP GNSSInternetRadio 2.0.10")
            .append("Accept: */*")
            .append("Connection: close")
            .append("Accept:*/*")
            .append("Authorization: Basic $base64")
            .toString()
        socketClient.sendMessage(msg.toByteArray())
    }

    override fun onConnectFailed() {

    }

    override fun onDisconnected() {

    }

    override fun onMessageReceived(bytes: ByteArray?) {
        bytes?.apply {
            if (size == 14) {
                /**
                 * 连接成功
                 * <p>
                 * ICY 200 OK
                 * */
                val result = String(this, StandardCharsets.UTF_8)
                if (result.contains("ICY 200 OK")) {
                    lifecycleScope.launch(Dispatchers.Main) {
                        "高精度定位服务连接成功".show(this@NtripConnectService)
                    }
                    //连接服务即打开串口
                    outStream = BaseApplication.get().getSerialPorts().first().outputStream
                }
            } else if (size == 153) {
                Log.d(kTag, String(this, StandardCharsets.UTF_8))
                /**
                 * 账号到期
                 * <p>
                 * HTTP 401 Unauthorized
                 * Server: POP_GW_Ntrip_1.0_1729082016/1.0
                 * Via: n108_10
                 * Date: 2024/11/08 14:01:18
                 * Content-Type: text/plain
                 * Connection: clos
                 * */
                lifecycleScope.launch(Dispatchers.Main) {
                    "差分定位服务鉴权失败，无法解析位置".show(this@NtripConnectService)
                }
            } else {
                //居中显示
                lifecycleScope.launch(Dispatchers.Main) {
                    val toast = Toast.makeText(
                        this@NtripConnectService, "收到千寻数据，长度：${size}", Toast.LENGTH_SHORT
                    )
                    toast.setGravity(Gravity.CENTER, 0, 0)
                    toast.show()
                }

                outStream?.write(this)
                outStream?.flush()
            }
        }
    }

    private fun connectQianXunServer() {
        //取缓存
        val remoteHost = SaveKeyValues.getValue(
            LocaleConstant.RTK_SERVER, "203.107.45.154"
        ) as String
        val remotePort = SaveKeyValues.getValue(
            LocaleConstant.RTK_PORT, "8003"
        ) as String

        if (socketClient.isRunning()) {
            return
        }

        socketClient.start(remoteHost, remotePort.toInt())
    }
}