package producer

import (
	"fmt"
	"image"
	"math"

	"github.com/airbusgeo/godal"
	log "github.com/sirupsen/logrus"
	"gocv.io/x/gocv"
	"starwiz.cn/sjy01/image-proc/pkg/config"
)

func GTiffToJPG(ftiff, fjpg, sensor string, reversed bool) error {
	// 打开 TIFF 文件
	ds, err := godal.Open(ftiff)
	if err != nil {
		log.Printf("Error opening TIFF file %s: %v", ftiff, err)
		return err
	}
	defer ds.Close()

	bands := ds.Bands()
	log.Infof("creating JPG for TIFF file %s.", ftiff)

	// 获取图像大小
	width := bands[0].Structure().SizeX
	height := bands[0].Structure().SizeY
	bandsCnt := len(bands)

	// 创建 16 位图像矩阵
	var img gocv.Mat
	defer img.Close()
	if bandsCnt == 1 {
		img = gocv.NewMatWithSize(height, width, gocv.MatTypeCV16UC1)
	} else {
		bandsCnt = 3 // 只取前三个波段
		img = gocv.NewMatWithSize(height, width, gocv.MatTypeCV16UC3)
	}

	// 读取每个波段并存储到图像矩阵中
	for i := 0; i < bandsCnt; i++ {
		band := bands[i]
		data := make([]uint16, width*height)
		err = band.Read(0, 0, data, width, height)
		if err != nil {
			fmt.Printf("Error reading band %d: %v\n", i, err)
			return err
		}

		// 将 16 位数据存储到图像的相应通道
		for y := 0; y < height; y++ {
			for x := 0; x < width; x++ {
				value := data[y*width+x]
				img.SetShortAt(y, x*bandsCnt+i, int16(value))
			}
		}
	}

	channels := gocv.Split(img)
	enhancement, ok := config.GCONFIG.BrowserImg.Enhancement[sensor]
	if !ok {
		enhancement = "NoEnhancement"
	}
	for i, ch := range channels {
		switch enhancement {
		case StretchToCumulativeCutMinMax:
			channels[i] = cumulativeCountCutEnhancement(ch,
				config.GCONFIG.BrowserImg.CumulativeCutLower,
				config.GCONFIG.BrowserImg.CumulativeCutUpper)
			ch.Close()
		default:
			minVal, maxVal, _, _ := gocv.MinMaxLoc(ch)
			ce := NewContrastEnhancement(int(minVal), int(maxVal))
			for y := 0; y < height; y++ {
				for x := 0; x < width; x++ {
					value := int(uint16(ch.GetShortAt(y, x)))
					value = ce.enhance(value)
					ch.SetShortAt(y, x, int16(value))
				}
			}
		}

	}

	img8bit := gocv.NewMat()
	defer img8bit.Close()
	if reversed {
		gocv.Merge([]gocv.Mat{channels[2], channels[1], channels[0]}, &img8bit)
	} else {
		gocv.Merge(channels, &img8bit)
	}

	for i := range channels {
		channels[i].Close()
	}

	gocv.Resize(img8bit, &img8bit,
		image.Point{X: img8bit.Cols() / 2, Y: img8bit.Rows() / 2},
		0, 0, gocv.InterpolationCubic)

	gocv.IMWrite(fjpg, img8bit)

	// 7. 应用伽玛校正提升亮度
	// gammaCorrected := applyGammaCorrection(img8bit, 1.6) // 伽玛值
	// defer gammaCorrected.Close()
	// ok := gocv.IMWriteWithParams(fjpg, gammaCorrected, []int{gocv.IMWriteJpegOptimize, 1})
	// if !ok {
	// 	err = fmt.Errorf("error saving %s", fjpg)
	// 	return err
	// }
	return nil
}

// applyGammaCorrection applies gamma correction to the image
func applyGammaCorrection(src gocv.Mat, gamma float64) gocv.Mat {
	lookupTable := make([]uint8, 256)
	invGamma := 1.0 / gamma
	for i := 0; i < 256; i++ {
		lookupTable[i] = uint8(math.Pow(float64(i)/255.0, invGamma) * 255.0)
	}

	dst := gocv.NewMat()
	gammaMat, err := gocv.NewMatFromBytes(1, 256, gocv.MatTypeCV8UC1, lookupTable)
	if err != nil {
		log.Printf("Error creating gamma correction matrix: %v", err)
		return src
	}
	defer gammaMat.Close()

	gocv.LUT(src, gammaMat, &dst)
	return dst
}
