package nori

import (
	"bufio"
	"encoding/binary"
	"fmt"
	"image"
	"image/color"
	"io"
)

type Image struct {
	Bpp     uint32
	Count   uint32
	Delay   uint32
	OffsetX int32
	OffsetY int32

	Width  uint32
	Height uint32

	Size uint32
	Data []byte

	Img image.Image
}

func (i *Image) Decode(rd *bufio.Reader, palette *PaletteSection) error {
	cf := image.NewRGBA64(image.Rect(0, 0, int(i.Width), int(i.Height)))
	i.Img = cf
	switch i.Bpp {
	case 8:
		if palette == nil {
			return fmt.Errorf("bpp = 8, but no palette")
		}
		for idx := 0; idx < int(i.Size); idx++ {
			b, err := rd.ReadByte()
			if err != nil {
				return err
			}
			col := palette.Palette[b]
			cf.Set(idx%int(i.Width), idx/int(i.Width), col)
		}
		return nil
	case 16:
		var bgr uint16
		for idx := 0; idx < int(i.Size/2); idx++ {
			if err := binary.Read(rd, end, &bgr); err != nil {
				return err
			}
			red := uint8(((0x7c00 & bgr) >> 10) * 255 / 31)
			green := uint8(((0x3e0 & bgr) >> 5) * 255 / 31)
			blue := uint8((0x1f & bgr) * 255 / 31)
			alpha := uint8(0xff)
			if red == 0xff && blue == 0xff {
				alpha = 0x00
			}
			if red == 0x00 && blue == 0x00 && green == 0xff {
				alpha = 0x00
			}
			col := &color.RGBA{
				red, green, blue,
				alpha,
			}
			cf.Set(idx%int(i.Width), idx/int(i.Width), col)
		}
		return nil
	case 24:
		i.Data = make([]byte, i.Size)
		for idx := 0; idx < int(i.Size/3); idx++ {
			rgb := [3]byte{}
			_, err := io.ReadFull(rd, rgb[:])
			if err != nil {
				return err
			}
			alpha := uint8(0xff)
			col := &color.RGBA{
				rgb[0], rgb[1], rgb[2],
				alpha,
			}

			if rgb[0] == 0x00 && rgb[1] == 0xff && rgb[2] == 0x00 {
				alpha = 0x00
			}
			if rgb[0] == 0xff && rgb[2] == 0xff {
				alpha = 0x00
			}
			cf.Set(idx%int(i.Width), idx/int(i.Width), col)
		}
		return nil
	default:
		return fmt.Errorf("unsupported bpp, %d", i.Bpp)
	}
}
