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

import android.app.Service
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.Handler
import android.os.IBinder
import android.os.Message
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.utils.tcp.ConnectState
import com.casic.common.detector.gd.utils.tcp.OnSocketConnectListener
import com.casic.common.detector.gd.utils.tcp.SocketClient
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 io.netty.buffer.Unpooled
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.io.OutputStream
import java.nio.charset.StandardCharsets

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

    companion object {
        var weakReferenceHandler: WeakReferenceHandler? = null
    }

    private val kTag = "NtripConnectService"
    private val registry = LifecycleRegistry(this)
    private var connectState = ConnectState.CLOSED
    private var serialPortService: SerialPortService? = null
    private var outStream: OutputStream? = null
    private lateinit var socketClient: SocketClient

    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)
        //绑定串口通信服务
        Intent(this, SerialPortService::class.java).also {
            bindService(it, serviceConnection, Context.BIND_AUTO_CREATE)
        }

        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 (connectState == ConnectState.SUCCESS) {
                //连接成功就发送千寻请求报文
                val gga = it.convertToGPGGA()
                Log.d(kTag, gga)
                socketClient.sendData(gga)
            }
        }
    }

    private val serviceConnection = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, iBinder: IBinder?) {
            if (iBinder is SerialPortService.ServiceBinder) {
                serialPortService = iBinder.getSerialPortService()
                Log.d(kTag, "onServiceConnected: 服务已绑定")
            }
        }

        override fun onServiceDisconnected(name: ComponentName?) {

        }
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        lifecycleScope.launch(Dispatchers.IO) {
            connectQianXunServer()
        }
        return START_STICKY
    }

    override fun onMessageResponse(data: ByteArray) {
        if (data.size == 14) {
            /**
             * 连接成功，登录会返回 ICY 200 OK
             * <p>
             * 0d0a0d0a -> \r\n\r\n
             * */
            val result = String(data, StandardCharsets.UTF_8)
            if (result.contains("ICY 200 OK")) {
                "高精度定位服务连接成功".show(this)
                //连接服务即打开串口
                outStream = BaseApplication.get().getSerialPorts().first().outputStream
            }
        } else {
            //居中显示
            val toast = Toast.makeText(this, "收到千寻数据，长度：${data.size}", Toast.LENGTH_SHORT)
            toast.setGravity(Gravity.CENTER, 0, 0)
            toast.show()

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

    override fun onServiceConnectStatusChanged(status: ConnectState) {
        this.connectState = status
        Log.d(kTag, "onServiceConnectStatusChanged: $status")
        if (connectState == ConnectState.SUCCESS) {
            //连接成功就发送千寻请求报文
            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 = android.util.Base64.encodeToString(byteArray, android.util.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()

            val byteBuf = Unpooled.wrappedBuffer(msg.toByteArray())
            socketClient.sendData(byteBuf)
        }
    }

    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

        socketClient = SocketClient.Builder()
            .setHostname(remoteHost)
            .setPort(remotePort.toInt())
            .setTimeout(5000)
            .setOnSocketListener(this)
            .build()
        socketClient.connect()
    }

    override fun onDestroy() {
        super.onDestroy()
        unbindService(serviceConnection)
    }
}