package com.inzy.wsmock.push

import com.alibaba.fastjson2.JSON
import com.alibaba.fastjson2.JSONObject
import com.inzy.wsmock.ChannelManager
import com.inzy.wsmock.RequestParamHandler
import com.inzy.wsmock.bean.RouteCarVeh
import com.inzy.wsmock.bean.ParkPath
import com.inzy.wsmock.bean.V2xStartBean
import com.inzy.wsmock.bean.VObject
import com.inzy.wsmock.utils.FileIoUtil
import com.inzy.wsmock.utils.MyMapUtils
import com.sd.cavphmi.bean.CarVehBak
import io.netty.channel.Channel
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame
import jakarta.annotation.PostConstruct
import jakarta.annotation.PreDestroy
import kotlinx.coroutines.*
import kotlinx.coroutines.time.delay
import org.slf4j.LoggerFactory
import org.springframework.core.io.ResourceLoader
import org.springframework.stereotype.Component
import java.util.concurrent.atomic.AtomicBoolean

@Component
//@Scope("prototype")
class AvpPushTask(
    // 注入Spring资源加载器（Spring自动装配）
    private val resourceLoader: ResourceLoader,
//    private val pushConfig: PushConfig,
) : PushTask {
    //    private val instanceId = System.currentTimeMillis()  // 实例唯一标识，用于验证多实例
    private val logger = LoggerFactory.getLogger(javaClass)


    // 注入ChannelManager单例
    private val channelManager = ChannelManager.instance

    //车辆位姿
    private var carBak = CarVehBak()

    //车辆位姿，泊车
//    private var carDstPark = mutableListOf<String>()
    private var carVehPark: RouteCarVeh? = null

    //车辆位姿，倒车入库
    //倒车路径
    private var parkPath: ParkPath? = null

    //车辆位姿，召车
    private var carVehCall: RouteCarVeh? = null

    //车辆行驶的位置
    private var carIndex = 0

    //AVP状态 park call
    private var status = ""

    //感知物
    private var preDst = mutableListOf<String>()


    //v2x只推一次开关
    private var isV2x = AtomicBoolean(false)

    @PostConstruct
    fun readMockFile() {
//        logger.info("创建 AdasPushTask 实例，ID: $instanceId")
        var classpathResource = resourceLoader.getResource("classpath:avpm/Car_fangzhen_park.txt")
        // 读取文件内容（Kotlin简化写法）
        CoroutineScope(Dispatchers.IO).launch {
            //读取泊车数据
            val parkStr = FileIoUtil.getFileDate(classpathResource.inputStream)
            carVehPark = JSON.parseObject(parkStr, RouteCarVeh::class.java)
            //计算航向角
            carVehPark!!.rs?.forEachIndexed { i, doubles ->
                if (i > 0) {
                    val p1 = carVehPark?.rs!!.get(i - 1)
                    val pc = doubles
                    val head = MyMapUtils.calculateBearing(
                        p1[0], p1[1],
                        pc[0], pc[1]
                    )
                    doubles.add(head)
                } else {
                    carVehPark!!.rs!!.get(0).add(0.0)
                }
            }
            //读取倒车入库数据
            classpathResource = resourceLoader.getResource("classpath:avpm/parkpath.txt")
            val parking = FileIoUtil.getFileDate(classpathResource.inputStream)
            parkPath = JSON.parseObject(parking, ParkPath::class.java)

            //读取召车数据
            classpathResource = resourceLoader.getResource("classpath:avpm/Car_fangzhen_call.txt")
            val callStr = FileIoUtil.getFileDate(classpathResource.inputStream)
            carVehCall = JSON.parseObject(callStr, RouteCarVeh::class.java)
            //计算航向角
            carVehCall!!.rs?.forEachIndexed { i, doubles ->
                if (i > 0) {
                    val p1 = carVehCall?.rs!!.get(i - 1)
                    val pc = doubles
                    val head = MyMapUtils.calculateBearing(
                        p1[0], p1[1],
                        pc[0], pc[1]
                    )
                    doubles.add(head)
                } else {
                    carVehCall!!.rs!!.get(0).add(0.0)
                }
            }

            //读取感知物数据
            classpathResource = resourceLoader.getResource("classpath:avpm/PerTarget.txt")
            FileIoUtil.getMockToList(classpathResource.inputStream, preDst)
        }
    }

    @PreDestroy
    fun destroy() {
//        logger.info("销毁 AdasPushTask 实例，ID: $instanceId")
        preDst.clear()
    }

    override fun pushMsgFromType(type: String, channel: Channel) {
        when (type) {
            RequestParamHandler.PARAM_TYPE_VALUE_1 -> {//车辆位姿
                pushCarPos(channel)
            }

            RequestParamHandler.PARAM_TYPE_VALUE_2 -> {//感知物
                pushPre(channel)
            }

            RequestParamHandler.PARAM_TYPE_VALUE_3 -> {//v2x 预警
                pushV2x(channel)
            }

            else -> {
//                val msg = JSONObject()
//                msg.put("type", "avp")
//                sendMsg(channel, msg.toJSONString())
            }
        }
    }


    /**
     * 推送车辆位姿
     */
    private fun pushCarPos(channel: Channel) {
        CoroutineScope(Dispatchers.Default).launch {
            delay(18000)
            if (carVehPark?.rs?.count() == 0 || carVehCall?.rs?.count() == 0)
                return@launch
            status = "park"
            //开始推送泊车
            carBak.businessStatus = status

            carVehPark!!.status = status
            carVehPark!!.rs?.forEachIndexed { i, doubles ->
                carIndex++
                carBak.vehiclePos = doubles
                carBak.carPos = i
                sendMsg(channel, JSON.toJSONString(carBak))
                delay(300)
            }
            //开始倒车入库
            status = "parking"
            carBak.businessStatus = status
            carBak.carPos = -1
            //开始后退
            val forback = parkPath!!.result.routes.find { it.gear == 1 }
            forback?.polyline?.forEachIndexed { index, doubles ->
                carIndex++
                carBak.vehiclePos = listOf<Double>(doubles[0], doubles[1], doubles[3])
                sendMsg(channel, JSON.toJSONString(carBak))
                delay(300)
            }
            //泊车完成
            status = "park_com"
            carBak.businessStatus = status
            carBak.vehiclePos = emptyList()
            //泊车完成消息
            sendMsg(channel, JSON.toJSONString(carBak))
            delay(3000)


            //开始推送召车
            status = "call"
            carBak.businessStatus = status
            carVehCall!!.rs?.forEachIndexed { i, doubles ->
                carIndex++
                carBak.vehiclePos = doubles
                carBak.carPos = i
                sendMsg(channel, JSON.toJSONString(carBak))
                delay(300)
            }
            delay(1000)
            //召车完成
            status = "call_com"
            carBak.businessStatus = status
            carBak.vehiclePos = emptyList()
            //发送召车完成消息
            sendMsg(channel, JSON.toJSONString(carBak))
            //全部完成
            carIndex = 0
            status = ""
            carBak.businessStatus = status
            carBak.carPos = 0
            carBak.vehiclePos = emptyList()
            sendMsg(channel, JSON.toJSONString(carBak))
            /* carVehCall?.apply {
                 this.status = this@AvpPushTask.status
                 carPos = 0
                 rs = listOf()
             }
             sendMsg(channel, JSON.toJSONString(carVehCall))*/
        }
    }

    private fun pushPark() {

    }


    /**感知物**/
    private fun pushPre(channel: Channel) {
        CoroutineScope(Dispatchers.Default).launch {
            if (preDst.isNotEmpty()) {
                delay(2000)
                preDst.forEachIndexed { index, string ->
//                            println("index = ${index}")
                    sendMsg(channel, string)
                    delay(4500)
                }
                pushPre(channel)
            }
        }
    }

    private fun pushV2x(channel: Channel) {
        CoroutineScope(Dispatchers.Default).launch {
            while (isActive) {
//                carPos = 0
                val carPos = carBak.carPos
//                println("----------carPos ${carPos}  status ${status}")
                if (carPos == 0 || status.equals("")) {
                    delay(100)
                    continue
                }
                if (status.equals("park")) {
                    when (carPos) {
                        8 -> {//紧急制动预警
//                            val v2x = V2xStartBean().apply {
//                                type = 6
//                                objects =
//                                    listOf(VObject(""), VObject("f117fdfa-feff-0100-85dc-35850000acb0"))
//                            }
                            pushV2xAtomic(channel, 6, "f117fdfa-feff-0100-85dc-35850000acb0")
                        }

                        30 -> {//前向碰撞
                            /*       val v2x = V2xStartBean().apply {
                                       type = 1
                                       objects =
                                           listOf(VObject(""), VObject("f117fdfa-feff-0100-85dc-35850000acb0"))
                                   }*/
                            pushV2xAtomic(channel, 1, "f117fdfa-feff-0100-85dc-35850000acb0")
                        }

                        60 -> {//弱势交通参与者
                            /*     val v2x = V2xStartBean().apply {
                                     type = 12
                                     objects =
                                         listOf(VObject(""), VObject("50332456-3030-3030-3530-303334533955"))
                                 }*/
                            pushV2xAtomic(channel, 12, "50332456-3030-3030-3530-303334533955")
                        }
                    }

                } else if (status.equals("call")) {
                    when (carPos) {
                        70 -> {//盲区预警
                            /*      val v2x = V2xStartBean().apply {
                                      type = 4
                                      objects =
                                          listOf(VObject(""), VObject("2435"))
                                  }*/
                            pushV2xAtomic(channel, 4, "2345")
                        }
                    }
                }
                delay(200)
            }
        }
    }

    private fun pushV2xAtomic(channel: Channel, v2xStartBean: V2xStartBean, change: Boolean = true) {
        if (isV2x.compareAndSet(false, true)) {
//            val msgObj = JSONObject()
//            msgObj["content"] = "定时推送消息 type=2 ${LocalDateTime.now()}"
            val str = JSONObject.toJSONString(v2xStartBean)
            sendMsg(channel, str)
            if (change) {
                isV2x.set(false)
            }
        }
    }

    private fun pushV2xAtomic(channel: Channel, type: Int, id: String, change: Boolean = true) {
        if (isV2x.compareAndSet(false, true)) {
            val v2x = V2xStartBean().apply {
                this.type = type
                objects =
                    listOf(VObject(""), VObject(id))
            }
            val str = JSONObject.toJSONString(v2x)
            sendMsg(channel, str)
            if (change) {
                isV2x.set(false)
            }
        }
    }


    private fun sendMsg(channel: Channel, msg: String) {
        if (!channel.isActive()) {
//            println("无在线客户端，跳过推送")
            channelManager.removeChannel(channel)
            return
        }
        val clientId = channel.id().asShortText()
        val frame = TextWebSocketFrame(msg)
        channel.writeAndFlush(frame)
            .addListener { future ->
                if (!future.isSuccess) {
                    println("推送消息给客户端[$clientId]失败：${future.cause()?.message}")
                    channelManager.removeChannel(channel) // 推送失败移除失效Channel
                }
            }
    }


}