package sprite

import (
	"image"
	"math"
)

type Sprite struct {
	Name     string
	Position image.Point
	Image    image.Image
	Index    int
}

func (s *Sprite) SetImage(img *image.RGBA) {
	s.Image = img
}

func (s *Sprite) Rotate(angle float64) {
	// 创建旋转矩阵
	sin, cos := math.Sin(angle), math.Cos(angle)

	// 获取原始图像的边界
	bounds := s.Image.Bounds()
	width, height := bounds.Dx(), bounds.Dy()
	centerX, centerY := width/2, height/2

	// 计算旋转后图像的边界
	corners := [4][2]int{
		{0 - centerX, 0 - centerY},
		{width - centerX, 0 - centerY},
		{0 - centerX, height - centerY},
		{width - centerX, height - centerY},
	}

	// 计算旋转后的四个角点位置
	minX, minY, maxX, maxY := 0, 0, 0, 0
	for i, p := range corners {
		// 应用旋转
		rotX := int(cos*float64(p[0]) - sin*float64(p[1]))
		rotY := int(sin*float64(p[0]) + cos*float64(p[1]))

		// 更新边界
		if i == 0 || rotX < minX {
			minX = rotX
		}
		if i == 0 || rotY < minY {
			minY = rotY
		}
		if i == 0 || rotX > maxX {
			maxX = rotX
		}
		if i == 0 || rotY > maxY {
			maxY = rotY
		}
	}

	// 创建新图像
	newWidth, newHeight := maxX-minX+1, maxY-minY+1
	newImage := image.NewRGBA(image.Rect(0, 0, newWidth, newHeight))
	newCenterX, newCenterY := newWidth/2, newHeight/2

	// 预计算矩阵常量
	invSin, invCos := math.Sin(-angle), math.Cos(-angle)

	// 使用查找表存储sin/cos值，避免重复计算
	srcXOrigin := make([]int, newWidth)
	srcYOrigin := make([]int, newHeight)

	// 预计算X坐标的变换
	for x := 0; x < newWidth; x++ {
		srcXOrigin[x] = centerX
	}

	// 预计算Y坐标的变换
	for y := 0; y < newHeight; y++ {
		srcYOrigin[y] = centerY
	}

	// 批量处理像素
	for y := 0; y < newHeight; y++ {
		srcY := y - newCenterY

		for x := 0; x < newWidth; x++ {
			srcX := x - newCenterX

			// 应用逆向旋转矩阵
			origX := int(invCos*float64(srcX)-invSin*float64(srcY)) + centerX
			origY := int(invSin*float64(srcX)+invCos*float64(srcY)) + centerY

			// 检查是否在原图范围内
			if origX >= 0 && origX < width && origY >= 0 && origY < height {
				newImage.Set(x, y, s.Image.At(origX, origY))
			}
		}
	}

	s.Image = newImage
}

func (s *Sprite) Move(x, y int) {
	s.Position.X += x
	s.Position.Y += y
}

func (s *Sprite) Project(projectMatrix *ProjectMatrix) {
	bounds := s.Image.Bounds()

	// 计算四个角点投影后的位置
	minX, minY, maxX, maxY := 0, 0, 0, 0

	// 预先计算所有角点的投影，一次性确定边界
	corners := [4]image.Point{
		{bounds.Min.X, bounds.Min.Y},
		{bounds.Max.X, bounds.Min.Y},
		{bounds.Min.X, bounds.Max.Y},
		{bounds.Max.X, bounds.Max.Y},
	}

	for i, corner := range corners {
		projected := projectMatrix.ProjectPoint(corner)
		if i == 0 {
			minX, minY = projected.X, projected.Y
			maxX, maxY = projected.X, projected.Y
		} else {
			if projected.X < minX {
				minX = projected.X
			}
			if projected.Y < minY {
				minY = projected.Y
			}
			if projected.X > maxX {
				maxX = projected.X
			}
			if projected.Y > maxY {
				maxY = projected.Y
			}
		}
	}

	// 创建新图像
	newWidth, newHeight := maxX-minX+1, maxY-minY+1
	newImage := image.NewRGBA(image.Rect(0, 0, newWidth, newHeight))

	// 计算逆矩阵
	det := projectMatrix.Matrix[0][0]*projectMatrix.Matrix[1][1] -
		projectMatrix.Matrix[0][1]*projectMatrix.Matrix[1][0]
	if math.Abs(det) < 1e-6 {
		// 矩阵接近不可逆
		return
	}

	invDet := 1.0 / det
	invMatrix := [2][2]float64{
		{projectMatrix.Matrix[1][1] * invDet, -projectMatrix.Matrix[0][1] * invDet},
		{-projectMatrix.Matrix[1][0] * invDet, projectMatrix.Matrix[0][0] * invDet},
	}

	// 预计算变换常量
	m00, m01 := invMatrix[0][0], invMatrix[0][1]
	m10, m11 := invMatrix[1][0], invMatrix[1][1]

	// 使用直接内存访问优化像素设置
	dstRGBA := newImage.Pix
	srcImg, srcRGBA, _ := getImageBytes(s.Image)

	// 批量处理像素
	for y := 0; y < newHeight; y++ {
		srcY := float64(y + minY)

		for x := 0; x < newWidth; x++ {
			srcX := float64(x + minX)

			// 使用逆矩阵计算
			origX := int(m00*srcX + m01*srcY)
			origY := int(m10*srcX + m11*srcY)

			// 检查边界
			if origX >= bounds.Min.X && origX < bounds.Max.X &&
				origY >= bounds.Min.Y && origY < bounds.Max.Y {
				// 设置像素 - 直接使用indexing会更快
				if srcRGBA != nil {
					// 如果源图像是RGBA格式，直接复制像素
					dstIdx := (y*newImage.Stride + x*4)
					srcIdx := ((origY-bounds.Min.Y)*srcImg.Stride + (origX-bounds.Min.X)*4)

					dstRGBA[dstIdx] = srcRGBA[srcIdx]     // R
					dstRGBA[dstIdx+1] = srcRGBA[srcIdx+1] // G
					dstRGBA[dstIdx+2] = srcRGBA[srcIdx+2] // B
					dstRGBA[dstIdx+3] = srcRGBA[srcIdx+3] // A
				} else {
					// 否则使用通用方法
					newImage.Set(x, y, s.Image.At(origX, origY))
				}
			}
		}
	}

	s.Image = newImage
}

func (s *Sprite) DrawLine(line *Line) {
	// 使用Line.ToSprite方法在当前精灵上绘制线条
	line.AddToSprite(s)
}

// getImageBytes 尝试提取图像的原始字节数据以加速访问
func getImageBytes(img image.Image) (*image.RGBA, []uint8, bool) {
	if rgba, ok := img.(*image.RGBA); ok {
		return rgba, rgba.Pix, true
	}
	return nil, nil, false
}
