package nori

import (
	"fmt"
	"image"
	"image/draw"

	"git.tuxpa.in/a/zlog/log"
	"github.com/phrozen/blend"
	"gitlab.com/gfxlabs/gfximg/apng"
)

func (n *Nori) ShowAnimation() *apng.APNG {
	g := n.Gawi
	a := &apng.APNG{
		Frames: make([]apng.Frame, 0, len(g.Images)),
	}
	for i := 0; i < len(g.Images); i++ {
		fr := apng.Frame{
			Image:            g.Images[i].Img,
			DelayNumerator:   uint16(g.Images[i].Delay),
			DelayDenominator: 1000,
		}
		a.Frames = append(a.Frames, fr)
	}
	return a
}

func (n *Nori) ExportAnimation(num int) (*apng.APNG, error) {
	g := n.Gawi
	a := &apng.APNG{
		Frames: make([]apng.Frame, 0, len(g.Images)),
	}
	if len(n.Animations[num].Frames) == 0 {
		return nil, fmt.Errorf("no frames found for animation")
	}
	images := make([]*image.NRGBA64, 0, len(n.Animations[num].Frames))
	for _, frame := range n.Animations[num].Frames {
		planes := frame.Planes
		var canvasRect image.Rectangle
		for _, plane := range planes {
			if int(plane.BitmapId) >= len(n.Gawi.Images) {
				log.Printf("could not find bitmap %d, only have %d", plane.BitmapId, len(n.Gawi.Images))
			}
			bitmap := n.Gawi.Images[plane.BitmapId]
			pt := image.Pt(int(plane.PlaneX), int(plane.PlaneY)) // where to put the point
			rc := bitmap.Img.Bounds()
			canvasRect = canvasRect.Union(rc.Add(pt))
		}
		img := image.NewNRGBA64(canvasRect)
		for _, plane := range planes {
			bitmap := n.Gawi.Images[plane.BitmapId]
			transparent := false
			//flipx
			if plane.RenderFlag&1 != 0 {
			}
			//flipy
			if plane.RenderFlag&2 != 0 {
			}
			// is transparent
			if plane.RenderFlag&0x20 != 0 {
				transparent = true
			}
			_ = transparent
			pt := image.Pt(int(plane.PlaneX), int(plane.PlaneY)) // where to put the point
			src := bitmap.Img
			sr := src.Bounds()
			r := image.Rectangle{pt, pt.Add(sr.Size())}
			switch plane.Blend {
			case BlendMode_Alpha:
			case BlendMode_Mul, BlendMode_Mul7:
				blend.BlendImage(img, bitmap.Img, blend.Multiply)
			case BlendMode_Add, BlendMode_Add8:
				blend.BlendImage(img, bitmap.Img, blend.Add)
			case BlendMode_InvertMul, BlendMode_InvertMul5:
				blend.BlendImage(img, bitmap.Img, blend.Multiply)
			case BlendMode_None:
			default:
				return nil, fmt.Errorf("unknown blend mode: %d", plane.Blend)
			}
			draw.Draw(img,
				r,
				src,
				sr.Min,
				draw.Src,
			)
		}
		images = append(images, img)
	}
	or := images[0].Bounds()
	for _, realFrame := range images {
		or = realFrame.Bounds().Union(or)
	}
	if or.Size().X == 0 || or.Size().Y == 0 {
		return nil, fmt.Errorf("no frames found for animation")
	}
	for i, realFrame := range images {
		big := image.NewNRGBA64(or)
		draw.Draw(
			big,
			big.Rect,
			realFrame,
			realFrame.Bounds().Min,
			draw.Src,
		)
		fr := apng.Frame{
			Image:            big,
			DelayDenominator: 1000,
		}
		if g.Images[i].Delay != 0 {
			fr.DelayNumerator = uint16(g.Images[i].Delay)
		}
		a.Frames = append(a.Frames, fr)
	}
	log.Println(num, len(a.Frames))
	return a, nil
}
