// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package sprite provides a 2D scene graph for rendering and animation.
//
// A tree of nodes is drawn by a rendering Engine, provided by another
// package. The OS-independent Go version based on the image package is:
//
//	golang.org/x/mobile/exp/sprite/portable
//
// An Engine draws a screen starting at a root Node. The tree is walked
// depth-first, with affine transformations applied at each level.
//
// Nodes are rendered relative to their parent.
//
// Typical main loop:
//
//	for each frame {
//		quantize time.Now() to a clock.Time
//		process UI events
//		modify the scene's nodes and animations (Arranger values)
//		e.Render(scene, t, c)
//	}
package sprite // import "golang.org/x/mobile/exp/sprite"

import (
	"image"
	"image/draw"

	"golang.org/x/mobile/event/config"
	"golang.org/x/mobile/exp/f32"
	"golang.org/x/mobile/exp/sprite/clock"
)

type Arranger interface {
	Arrange(e Engine, n *Node, t clock.Time)
}

type Texture interface {
	Bounds() (w, h int)
	Download(r image.Rectangle, dst draw.Image)
	Upload(r image.Rectangle, src image.Image)
	Unload()
}

type SubTex struct {
	T Texture
	R image.Rectangle
}

type Engine interface {
	Register(n *Node)
	Unregister(n *Node)

	LoadTexture(a image.Image) (Texture, error)

	SetSubTex(n *Node, x SubTex)
	SetTransform(n *Node, m f32.Affine) // sets transform relative to parent.

	// Render renders the scene arranged at the given time, for the given
	// window configuration (dimensions and resolution).
	Render(scene *Node, t clock.Time, c config.Event)
}

// A Node is a renderable element and forms a tree of Nodes.
type Node struct {
	Parent, FirstChild, LastChild, PrevSibling, NextSibling *Node

	Arranger Arranger

	// EngineFields contains fields that should only be accessed by Engine
	// implementations. It is exported because such implementations can be
	// in other packages.
	EngineFields struct {
		// TODO: separate TexDirty and TransformDirty bits?
		Dirty  bool
		Index  int32
		SubTex SubTex
	}
}

// AppendChild adds a node c as a child of n.
//
// It will panic if c already has a parent or siblings.
func (n *Node) AppendChild(c *Node) {
	if c.Parent != nil || c.PrevSibling != nil || c.NextSibling != nil {
		panic("sprite: AppendChild called for an attached child Node")
	}
	last := n.LastChild
	if last != nil {
		last.NextSibling = c
	} else {
		n.FirstChild = c
	}
	n.LastChild = c
	c.Parent = n
	c.PrevSibling = last
}

// RemoveChild removes a node c that is a child of n. Afterwards, c will have
// no parent and no siblings.
//
// It will panic if c's parent is not n.
func (n *Node) RemoveChild(c *Node) {
	if c.Parent != n {
		panic("sprite: RemoveChild called for a non-child Node")
	}
	if n.FirstChild == c {
		n.FirstChild = c.NextSibling
	}
	if c.NextSibling != nil {
		c.NextSibling.PrevSibling = c.PrevSibling
	}
	if n.LastChild == c {
		n.LastChild = c.PrevSibling
	}
	if c.PrevSibling != nil {
		c.PrevSibling.NextSibling = c.NextSibling
	}
	c.Parent = nil
	c.PrevSibling = nil
	c.NextSibling = nil
}
