package com.casic.common.detector.gd.utils.tcp

import android.os.Looper
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LifecycleRegistry
import androidx.lifecycle.lifecycleScope
import io.netty.channel.ChannelHandlerContext
import io.netty.channel.SimpleChannelInboundHandler
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

class SocketChannelHandler(private val listener: OnSocketConnectListener) :
    SimpleChannelInboundHandler<ByteArray>(), LifecycleOwner {

    private fun isOnMainThread(): Boolean {
        return Looper.getMainLooper().thread == Thread.currentThread()
    }

    override fun channelActive(ctx: ChannelHandlerContext) {
        super.channelActive(ctx)
        if (isOnMainThread()) {
            listener.onServiceConnectStatusChanged(ConnectState.SUCCESS)
        } else {
            lifecycleScope.launch(Dispatchers.Main) {
                listener.onServiceConnectStatusChanged(ConnectState.SUCCESS)
            }
        }
    }

    override fun channelInactive(ctx: ChannelHandlerContext) {
        super.channelInactive(ctx)
        if (isOnMainThread()) {
            listener.onServiceConnectStatusChanged(ConnectState.CLOSED)
        } else {
            lifecycleScope.launch(Dispatchers.Main) {
                listener.onServiceConnectStatusChanged(ConnectState.CLOSED)
            }
        }
    }

    override fun channelRead0(channelHandlerContext: ChannelHandlerContext, bytes: ByteArray?) {
        if (bytes == null) {
            return
        }
        if (isOnMainThread()) {
            listener.onMessageResponse(bytes)
        } else {
            lifecycleScope.launch(Dispatchers.Main) {
                listener.onMessageResponse(bytes)
            }
        }
    }

    override fun exceptionCaught(ctx: ChannelHandlerContext, cause: Throwable) {
        super.exceptionCaught(ctx, cause)
        ctx.close()
        if (isOnMainThread()) {
            listener.onServiceConnectStatusChanged(ConnectState.ERROR)
        } else {
            lifecycleScope.launch(Dispatchers.Main) {
                listener.onServiceConnectStatusChanged(ConnectState.ERROR)
            }
        }
    }

    private val registry = LifecycleRegistry(this)

    override fun getLifecycle(): Lifecycle {
        return registry
    }
}