package img

import (
	"errors"
	"image"
	"image/color"
	"image/draw"
	"math"

	"github.com/disintegration/imaging"
	"github.com/fogleman/gg"
	"github.com/ssgo/u"
)

// Crop 裁剪图像
func (g *Graphics) Crop(x, y, w, h int) {
	rect := image.Rect(x, y, x+w, y+h)
	newImg := imaging.Crop(g.dc.Image(), rect)
	g.dc = gg.NewContextForImage(newImg)
}

// Contain 改变图片尺寸，保持图片比例，图片居中
func (g *Graphics) Contain(width, height int) {
	bounds := g.dc.Image().Bounds()
	srcW := bounds.Dx()
	srcH := bounds.Dy()
	ratio := math.Min(float64(width)/float64(srcW), float64(height)/float64(srcH))
	dstW := int(float64(srcW) * ratio)
	dstH := int(float64(srcH) * ratio)

	// 创建透明背景画布
	newImg := image.NewRGBA(image.Rect(0, 0, width, height))

	// 居中放置缩放后的图像
	offsetX := (width - dstW) / 2
	offsetY := (height - dstH) / 2
	resized := imaging.Resize(g.dc.Image(), dstW, dstH, imaging.Lanczos)
	draw.Draw(newImg,
		image.Rect(offsetX, offsetY, offsetX+dstW, offsetY+dstH),
		resized, image.Point{}, draw.Over)

	g.dc = gg.NewContextForImage(newImg)
}

// Cover 改变图片尺寸，保持图片比例，图片居中裁剪
func (g *Graphics) Cover(width, height int) {
	bounds := g.dc.Image().Bounds()
	srcW := bounds.Dx()
	srcH := bounds.Dy()
	ratio := math.Max(float64(width)/float64(srcW), float64(height)/float64(srcH))
	dstW := int(float64(srcW) * ratio)
	dstH := int(float64(srcH) * ratio)

	resized := imaging.Resize(g.dc.Image(), dstW, dstH, imaging.Lanczos)

	// 从中心裁剪
	cropX := max(0, (dstW-width)/2)
	cropY := max(0, (dstH-height)/2)
	cropped := imaging.Crop(resized,
		image.Rect(cropX, cropY, cropX+width, cropY+height))

	g.dc = gg.NewContextForImage(cropped)
}

// Resize 改变图片尺寸，拉伸
func (g *Graphics) Resize(width, height int, resampleMode *string) {
	resample := imaging.Lanczos
	if resampleMode != nil {
		switch *resampleMode {
		case "nearest":
			resample = imaging.NearestNeighbor
		case "catmullrom":
			resample = imaging.CatmullRom
		case "box":
			resample = imaging.Box
		case "linear":
			resample = imaging.Linear
		case "hermite":
			resample = imaging.Hermite
		case "mitchellnetravali":
			resample = imaging.MitchellNetravali
		case "bspline":
			resample = imaging.BSpline
		case "gaussian":
			resample = imaging.Gaussian
		case "bartlett":
			resample = imaging.Bartlett
		case "hann":
			resample = imaging.Hann
		case "hamming":
			resample = imaging.Hamming
		case "blackman":
			resample = imaging.Blackman
		case "welch":
			resample = imaging.Welch
		case "cosine":
			resample = imaging.Cosine
		default:
			resample = imaging.Lanczos
		}
	}
	resized := imaging.Resize(g.dc.Image(), width, height, resample)
	g.dc = gg.NewContextForImage(resized)
}

// Rotate 旋转图像
func (g *Graphics) Rotate(angle float64) {
	rotated := imaging.Rotate(g.dc.Image(), angle, color.Transparent)
	g.dc = gg.NewContextForImage(rotated)
}

// Blur 模糊图像
func (g *Graphics) Blur(sigma float64) {
	blurred := imaging.Blur(g.dc.Image(), sigma)
	g.dc = gg.NewContextForImage(blurred)
}

// Sharpen 锐化图像
func (g *Graphics) Sharpen(sigma float64) {
	sharpened := imaging.Sharpen(g.dc.Image(), sigma)
	g.dc = gg.NewContextForImage(sharpened)
}

// Grayscale 转为灰度图
func (g *Graphics) Grayscale() {
	gray := imaging.Grayscale(g.dc.Image())
	g.dc = gg.NewContextForImage(gray)
}

// AdjustBrightness 调整亮度
func (g *Graphics) AdjustBrightness(percent float64) {
	adjusted := imaging.AdjustBrightness(g.dc.Image(), percent)
	g.dc = gg.NewContextForImage(adjusted)
}

// AdjustContrast 调整对比度
func (g *Graphics) AdjustContrast(percent float64) {
	adjusted := imaging.AdjustContrast(g.dc.Image(), percent)
	g.dc = gg.NewContextForImage(adjusted)
}

// GammaCorrection Gamma校正
func (g *Graphics) GammaCorrection(gamma float64) {
	adjusted := imaging.AdjustGamma(g.dc.Image(), gamma)
	g.dc = gg.NewContextForImage(adjusted)
}

// FlipH 水平翻转
func (g *Graphics) FlipH() {
	flipped := imaging.FlipH(g.dc.Image())
	g.dc = gg.NewContextForImage(flipped)
}

// FlipV 垂直翻转
func (g *Graphics) FlipV() {
	flipped := imaging.FlipV(g.dc.Image())
	g.dc = gg.NewContextForImage(flipped)
}

// AdjustSaturation 调整饱和度
func (g *Graphics) AdjustSaturation(percent float64) {
	adjusted := imaging.AdjustSaturation(g.dc.Image(), percent)
	g.dc = gg.NewContextForImage(adjusted)
}

// func min(a, b int) int {
// 	if a < b {
// 		return a
// 	}
// 	return b
// }

// func max(a, b int) int {
// 	if a > b {
// 		return a
// 	}
// 	return b
// }

// Convolve3x3 应用3x3卷积核
func (g *Graphics) Convolve3x3(kernel []float64) error {
	if len(kernel) != 9 {
		return errors.New("kernel " + u.String(len(kernel)) + " must be 3x3")
	}

	// 获取图像大小
	bounds := g.dc.Image().Bounds()
	width, height := bounds.Dx(), bounds.Dy()

	// 创建新图像
	result := image.NewRGBA(bounds)

	// 卷积核权重和
	var sum float64
	for _, v := range kernel {
		sum += v
	}

	// 如果权重和不是0，则使用归一化因子
	scale := 1.0
	if sum != 0 {
		scale = 1.0 / sum
	}

	// 处理每个像素
	for y := 1; y < height-1; y++ {
		for x := 1; x < width-1; x++ {
			var r, g1, b, a float64

			// 应用卷积核
			for ky := -1; ky <= 1; ky++ {
				for kx := -1; kx <= 1; kx++ {
					k := kernel[(ky+1)*3+(kx+1)]
					px := g.dc.Image().At(x+kx, y+ky)
					pr, pg, pb, pa := px.RGBA()

					r += float64(pr>>8) * k
					g1 += float64(pg>>8) * k
					b += float64(pb>>8) * k
					a += float64(pa>>8) * k
				}
			}

			// 应用比例因子并限制范围
			r = math.Max(0, math.Min(255, r*scale))
			g1 = math.Max(0, math.Min(255, g1*scale))
			b = math.Max(0, math.Min(255, b*scale))
			a = math.Max(0, math.Min(255, a*scale))

			// 设置结果像素
			result.SetRGBA(x, y, color.RGBA{
				R: uint8(r),
				G: uint8(g1),
				B: uint8(b),
				A: uint8(a),
			})
		}
	}

	// 复制边界像素
	for y := 0; y < height; y++ {
		for x := 0; x < width; x++ {
			if y == 0 || y == height-1 || x == 0 || x == width-1 {
				result.Set(x, y, g.dc.Image().At(x, y))
			}
		}
	}

	g.dc = gg.NewContextForImage(result)
	return nil
}

// 带强度参数的滤镜应用
func (g *Graphics) ApplyFilter(kernel []float64, strength *float64) error {
	if len(kernel) != 9 {
		return errors.New("kernel " + u.String(len(kernel)) + " must be 3x3")
	}

	// 创建加权核
	weightedKernel := make([]float64, len(kernel))
	if strength == nil {
		copy(weightedKernel, kernel)
	} else {
		centerIdx := 4 // 3x3核心中心索引
		for i, v := range kernel {
			if i == centerIdx {
				weightedKernel[i] = 1 + *strength*(v-1)
			} else {
				weightedKernel[i] = *strength * v
			}
		}
	}
	return g.Convolve3x3(weightedKernel)
}

// 边缘检测
func (g *Graphics) EdgeDetectionFilter(strength *float64) {
	g.ApplyFilter([]float64{
		-1, -1, -1,
		-1, 8, -1,
		-1, -1, -1,
	}, strength)
}

// 高斯模糊
func (g *Graphics) GaussianBlurFilter(strength *float64) {
	g.ApplyFilter([]float64{
		1, 2, 1,
		2, 4, 2,
		1, 2, 1,
	}, strength)
}

// 锐化
func (g *Graphics) SharpenFilter(strength *float64) {
	g.ApplyFilter([]float64{
		-1, -1, -1,
		-1, 9, -1,
		-1, -1, -1,
	}, strength)
}

// 浮雕
func (g *Graphics) EmbossFilter(strength *float64) {
	g.ApplyFilter([]float64{
		-2, -1, 0,
		-1, 1, 1,
		0, 1, 2,
	}, strength)
}

// 散景模糊
func (g *Graphics) BokehFilter(strength *float64) {
	g.ApplyFilter([]float64{
		0, 0.1, 0,
		0.1, 0.6, 0.1,
		0, 0.1, 0,
	}, strength)
}
