package utils

import (
	"bytes"
	"errors"
	"fmt"
	"image"
	"image/color"
	"image/gif"
	_ "image/jpeg"
	_ "image/png"
	"io"
	"netease_control_center/interfaces/log"
	"os"
)

func ShowBytes(data []byte, width int) {
	fmt.Printf("\nwidth:%d:\n", width)
	for k, v := range data {
		//fmt.Printf("%02d  ", v)
		if k%width == 0 && k != 0 {
			fmt.Printf("\n")
		}
		if false {
			if v > 0 {
				fmt.Printf(" # ")
			} else {
				fmt.Printf(" @ ")
			}
		} else {
			fmt.Printf(" %02x", v)
		}

	}
}

func DecodeImage(path string) (er error, totalFrame int, delay int, oneImageSize int, picData []byte) {
	defer func() {
		if err := recover(); err != nil {
			log.Println(log.DebugLog, "Get error:", err)
			er = errors.New(fmt.Sprintln(err))
		}
	}()
	//log.Println(log.DebugLog, "Begin to show image:", path)
	if fd, err := os.Open(path); err == nil {
		if imgconfig, imgtype, imgtypeerr := image.DecodeConfig(fd); imgtypeerr == nil {
			fd.Seek(0, io.SeekStart)
			switch imgtype {
			case "jpeg", "png":
				if img, _, imgerr := image.Decode(fd); imgerr == nil {
					//log.Println(log.DebugLog, "Image bounds:", img.Bounds())
					buf := make([]byte, imgconfig.Height*imgconfig.Width)
					//buf2 := make([]color.Color, imgconfig.Height*imgconfig.Width)
					for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ {
						for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x++ {
							if cy, ok := color.GrayModel.Convert(img.At(x, y)).(color.Gray); ok && cy.Y > 19 {
								buf[y*imgconfig.Width+x] = byte(cy.Y) / 4
							}
							//buf2[y*imgconfig.Width+x] = img.At(x, y)
						}
					}
					err = nil
					oneImageSize = imgconfig.Height * imgconfig.Width
					picData = buf
					delay = 0xff
					totalFrame = 1
					//ShowBytes(buf, 9)
					return
				} else {
					log.Println(log.DebugLog, "Decode img error:", imgerr)
					er = imgerr
				}
				log.Println(log.DebugLog, "Show img end!!")
			case "gif":
				if gifimage, imageerr := gif.DecodeAll(fd); imageerr == nil {
					width := gifimage.Config.Width
					height := gifimage.Config.Height
					log.Println(log.DebugLog, "Get gif:", width, " x ", height, " Loop count:", gifimage.LoopCount, " delay:", gifimage.Delay[0], " Frame num:", len(gifimage.Image))
					buf := new(bytes.Buffer)
					frame := make([]byte, width*height)

					for _, onegif := range gifimage.Image {
						//log.Printf(log.DebugLog, "Get %d gif: %+v\n", k, *onegif)
						//fmt.Println("No.", k, " Rect:", onegif.Rect, " Stride:", onegif.Stride)
						for y := onegif.Rect.Min.Y; y < onegif.Rect.Max.Y; y++ {
							for x := onegif.Rect.Min.X; x < onegif.Rect.Max.X; x++ {
								ocolor := onegif.At(x, y)
								if co, ok := color.GrayModel.Convert(ocolor).(color.Gray); ok && co.Y > 19 {
									frame[y*width+x] = co.Y / 4
								}
							}
						}
						buf.Write(frame)
						//ShowBytes(frame, width)
					}

					delay = gifimage.Delay[0] * 10
					oneImageSize = gifimage.Config.Width * gifimage.Config.Height
					totalFrame = len(gifimage.Image)
					picData = buf.Bytes()
					//fmt.Println("\nShow total bytes!!!!")
					//ShowBytes(picData, 9)
				} else {
					log.Println(log.DebugLog, "Decode image error:", imageerr)
					er = imageerr
				}

			default:
				log.Println(log.DebugLog, "Unsupport the image type!")
				er = errors.New("Unsupport the image type!" + imgtype)
			}
		} else {
			log.Println(log.DebugLog, "Decode image type err:", imgtypeerr)
			er = imgtypeerr
		}
		fd.Close()
	} else {
		log.Println(log.ErrorLog, "Open file err:", err, " path:", path)
		er = err
	}

	return
}
