package image

import (
	"encoding/hex"
	"fmt"
	"image"
	"image/color"
	"sort"

	"b612.me/starlog"
	"github.com/spf13/cobra"
)

var useHex bool
var useAlpha bool
var useCount int
var ckt uint8
var fromRgb string
var toRgb string

func init() {
	Cmd.AddCommand(imgMirrorCmd, imgRgbCountCmd, imgReplaceCmd, imgReverseCmd)
	imgRgbCountCmd.Flags().BoolVarP(&useHex, "hex", "x", false, "使用十六进制表示")
	imgRgbCountCmd.Flags().BoolVarP(&useAlpha, "alpha", "a", false, "统计alpha通道")
	imgRgbCountCmd.Flags().IntVarP(&useCount, "count", "c", 10, "显示数量")
	imgReplaceCmd.Flags().Uint8VarP(&ckt, "ckt", "k", 30, "颜色比较阈值")
	imgReplaceCmd.Flags().StringVarP(&fromRgb, "from", "f", "dfdfdf", "需要替换的颜色")
	imgReplaceCmd.Flags().StringVarP(&toRgb, "to", "t", "ffffff", "替换为的颜色")
}

var Cmd = &cobra.Command{
	Use:   "image",
	Short: "图像处理",
	Long:  "简单的图像处理工具",
	Run: func(this *cobra.Command, args []string) {
		this.Help()
	},
}

var imgMirrorCmd = &cobra.Command{
	Use:   "mirror",
	Short: "图像镜像翻转",
	Long:  "图像镜像翻转<水平>",
	Run: func(this *cobra.Command, args []string) {
		if len(args) == 0 {
			starlog.Errorln("请指定需要转换的图像!")
			return
		}
		for _, v := range args {
			img, err := OpenImage(v)
			if err != nil {
				starlog.Errorln(err, v)
				continue
			}
			size := img.Bounds()
			nimg := image.NewRGBA(size)
			for x := 0; x < size.Dx(); x++ {
				for y := 0; y < size.Dy(); y++ {
					nimg.Set(size.Dx()-x, y, img.At(x, y))
				}
			}
			if err := SavePhoto(v, nimg); err != nil {
				starlog.Errorln(err, v)
				continue
			} else {
				fmt.Println(v, "转换已完成!")
			}
		}
		fmt.Println("任务完成!")
	},
}

var imgAlpha = &cobra.Command{
	Use:   "alpha",
	Short: "设置透明度",
	Long:  "设置alpha通道透明度",
	Run: func(this *cobra.Command, args []string) {
		if len(args) == 0 {
			starlog.Errorln("请指定需要转换的图像!")
			return
		}
		for _, v := range args {
			img, err := OpenImage(v)
			if err != nil {
				starlog.Errorln(err, v)
				continue
			}
			img = SetAlpha(img, 4)
			if err := SavePhoto(v, img); err != nil {
				starlog.Errorln(err, v)
				continue
			} else {
				fmt.Println(v, "转换已完成!")
			}
		}
		fmt.Println("任务完成!")
	},
}

var imgRgbCountCmd = &cobra.Command{
	Use:   "rgbcount",
	Short: "统计最多的rgb值",
	Long:  "统计最多的RGB值",
	Run: func(this *cobra.Command, args []string) {
		if len(args) == 0 {
			starlog.Errorln("请指定需要统计的图像!")
			return
		}
		for _, v := range args {
			img, err := OpenImage(v)
			if err != nil {
				starlog.Errorln(err, v)
				continue
			}
			size := img.Bounds()
			colorMap := make(map[string]int)
			for x := 0; x < size.Dx(); x++ {
				for y := 0; y < size.Dy(); y++ {
					color := img.At(x, y)
					r, g, b, a := color.RGBA()
					var key string
					if useAlpha {
						if !useHex {
							key = fmt.Sprintf("%d,%d,%d,%d", uint8(r>>8), uint8(g>>8), uint8(b>>8), uint8(a>>8))
						} else {
							key = fmt.Sprintf("%x%x%x%x", uint8(r>>8), uint8(g>>8), uint8(b>>8), uint8(a>>8))
						}
					} else {
						if !useHex {
							key = fmt.Sprintf("%d,%d,%d", uint8(r>>8), uint8(g>>8), uint8(b>>8))
						} else {
							key = fmt.Sprintf("%x%x%x", uint8(r>>8), uint8(g>>8), uint8(b>>8))
						}
					}
					if _, ok := colorMap[key]; ok {
						colorMap[key]++
					} else {
						colorMap[key] = 1
					}
				}
			}
			colorSlice := make([]struct {
				string
				int
			}, 0, len(colorMap))
			for k, v := range colorMap {
				colorSlice = append(colorSlice, struct {
					string
					int
				}{k, v})
			}
			sort.Slice(colorSlice, func(i, j int) bool {
				return colorSlice[i].int > colorSlice[j].int
			})
			fmt.Println(v)
			for i := 0; i < useCount && i < len(colorSlice); i++ {
				fmt.Printf("%d. %s: %d\n", i+1, colorSlice[i].string, colorSlice[i].int)
			}
			fmt.Println("----------------")
		}
		fmt.Println("任务完成!")
	},
}

var imgReplaceCmd = &cobra.Command{
	Use:   "replace",
	Short: "图像RGB替换",
	Long:  "图像RGB替换",
	Run: func(this *cobra.Command, args []string) {
		if len(args) == 0 {
			starlog.Errorln("请指定需要转换的图像!")
			return
		}
		r, g, b, err := HexToRGB(fromRgb)
		if err != nil {
			starlog.Errorln(err)
			return
		}
		nr, ng, nb, err := HexToRGB(toRgb)
		if err != nil {
			starlog.Errorln(err)
			return
		}
		for _, v := range args {
			img, err := OpenImage(v)
			if err != nil {
				starlog.Errorln(err, v)
				continue
			}
			size := img.Bounds()
			nimg := image.NewRGBA(size)
			for x := 0; x < size.Dx(); x++ {
				for y := 0; y < size.Dy(); y++ {
					mR, mG, mB, ma := img.At(x, y).RGBA()
					mr, mg, mb := uint8(mR>>8), uint8(mG>>8), uint8(mB>>8)
					nimg.Set(x, y, img.At(x, y))
					if mr-r < ckt || r-mr < ckt {
						if mg-g < ckt || g-mg < ckt {
							if mb-b < ckt || b-mb < ckt {
								nimg.Set(x, y, color.NRGBA{nr, ng, nb, uint8(ma >> 8)})
							}
						}
					}
				}
			}
			if err := SavePhoto("new-"+v, nimg); err != nil {
				starlog.Errorln(err, v)
				continue
			} else {
				fmt.Println(v, "转换已完成!")
			}
		}
		fmt.Println("任务完成!")
	},
}

func HexToRGB(hexStr string) (uint8, uint8, uint8, error) {
	// 检查输入长度是否为6
	if len(hexStr) != 6 {
		return 0, 0, 0, fmt.Errorf("invalid hex color string: %s", hexStr)
	}

	// 将16进制字符串解码为字节数组
	decoded, err := hex.DecodeString(hexStr)
	if err != nil {
		return 0, 0, 0, fmt.Errorf("failed to decode hex string: %v", err)
	}

	// 解码结果应该有3个字节
	if len(decoded) != 3 {
		return 0, 0, 0, fmt.Errorf("invalid hex color format: %s", hexStr)
	}

	// 返回三个通道值
	return decoded[0], decoded[1], decoded[2], nil
}

var imgReverseCmd = &cobra.Command{
	Use:   "reverse",
	Short: "图像反色",
	Long:  "图像反色",
	Run: func(this *cobra.Command, args []string) {
		if len(args) == 0 {
			starlog.Errorln("请指定需要转换的图像!")
			return
		}
		for _, v := range args {
			img, err := OpenImage(v)
			if err != nil {
				starlog.Errorln(err, v)
				continue
			}
			size := img.Bounds()
			nimg := image.NewRGBA(size)
			for x := 0; x < size.Dx(); x++ {
				for y := 0; y < size.Dy(); y++ {
					r, g, b, a := img.At(x, y).RGBA()
					nimg.Set(x, y, color.NRGBA{uint8(255 - r>>8), uint8(255 - g>>8), uint8(255 - b>>8), uint8(a >> 8)})
				}
			}
			if err := SavePhoto("reverse-"+v, nimg); err != nil {
				starlog.Errorln(err, v)
				continue
			} else {
				fmt.Println(v, "转换已完成!")
			}
		}
		fmt.Println("任务完成!")
	},
}