package main

//触发器名称:冲出车道

import (
	"cicv-data-closedloop/pjisuv_msgs"
	"fmt"
	"math"
	"sync"
)

func Topic() string {
	return "/map_polygon"
}

func Label() string {
	return "OutOfLane"
}

func Rule(shareVars *sync.Map, data *pjisuv_msgs.PolygonStamped) string {
	defer func() {
		if r := recover(); r != nil {
			fmt.Println("Recovered from panic:", r)
		}
	}()
	positionXOfCicvLocation, ok1 := shareVars.Load("PositionXOfCicvLocation")
	positionYOfCicvLocation, ok2 := shareVars.Load("PositionYOfCicvLocation")
	yawOfCicvLocation, ok3 := shareVars.Load("YawOfCicvLocation")
	automodeOfPjVehicleFdbPub, ok4 := shareVars.Load("AutomodeOfPjVehicleFdbPub")
	OutsideWorkshopFlag, _ := shareVars.Load("OutsideWorkshopFlag")
	OutsideWorkshopFlag = OutsideWorkshopFlag.(bool)
	if ok1 && ok2 && ok3 && ok4 {
		Points := data.Polygon.Points
		D1, D2, D3 := 1.0, 0.4, 0.4 //这是实车缩小后的尺寸
		corners := getVehicleCorners(positionXOfCicvLocation.(float64), positionYOfCicvLocation.(float64), D1, D2, D3, yawOfCicvLocation.(float64))
		for i := 0; i < len(Points)-1; i++ {
			A := Points[i]
			B := Points[i+1]
			if polygonLineIntersect(corners, A, B) && automodeOfPjVehicleFdbPub.(int16) == 1 && OutsideWorkshopFlag == true {
				return Label()
			}
		}
	}
	return ""
}

type Point struct {
	X, Y float64
}

func getVehicleCorners(x0, y0, D1, D2, D3, h0 float64) []pjisuv_msgs.Point64 {
	h0Rad := h0 * math.Pi / 180 // 转换角度到弧度
	cosH0, sinH0 := math.Cos(h0Rad), math.Sin(h0Rad)

	// 车辆四个角点相对于后轴中心点的坐标(局部坐标系)
	cornersLocal := []Point{
		{D1, D3},   // 前左角
		{D1, -D3},  // 前右角
		{-D2, D3},  // 后左角
		{-D2, -D3}, // 后右角
	}

	// 旋转矩阵并计算全局坐标
	rotationMatrix := [2][2]float64{{cosH0, -sinH0}, {sinH0, cosH0}}
	cornersGlobal := make([]pjisuv_msgs.Point64, len(cornersLocal))
	for i, corner := range cornersLocal {
		cornersGlobal[i].X = corner.X*rotationMatrix[0][0] + corner.Y*rotationMatrix[1][0] + x0
		cornersGlobal[i].Y = corner.X*rotationMatrix[0][1] + corner.Y*rotationMatrix[1][1] + y0
	}
	return cornersGlobal
}

func ccw(A, B, C pjisuv_msgs.Point64) bool {
	return (C.Y-A.Y)*(B.X-A.X) > (C.X-A.X)*(B.Y-A.Y)
}

func lineIntersect(A, B, C, D pjisuv_msgs.Point64) bool {
	return ccw(A, C, D) != ccw(B, C, D) && ccw(A, B, C) != ccw(A, B, D)
}

func polygonLineIntersect(polygon []pjisuv_msgs.Point64, A, B pjisuv_msgs.Point64) bool {
	for i := 0; i < len(polygon)-1; i++ {
		C := polygon[i]
		D := polygon[(i+1)%len(polygon)]
		if lineIntersect(A, B, C, D) {
			return true
		}
	}

	return false
}