package systems

import (
	"log/slog"
	"openquell/components"
	. "openquell/components"

	"github.com/hajimehoshi/ebiten/v2"
	"github.com/mlange-42/arche/ecs"
	"github.com/mlange-42/arche/generic"
)

type AnimationSystem struct {
	World    *ecs.World
	Selector *generic.Filter2[Position, Renderable]
	Cellsize int
}

func NewAnimationSystem(world *ecs.World, cellsize int) System {
	system := &AnimationSystem{
		Selector: generic.NewFilter2[Position, Renderable](),
		World:    world,
		Cellsize: cellsize,
	}

	return system
}

func (system *AnimationSystem) Update() error {
	EntitiesToRemove := []ecs.Entity{}

	query := system.Selector.Query(system.World)

	for query.Next() {
		_, render := query.Get()

		for animationtype, animate := range render.Animations() {
			if animate.Active {
				if animate.Timer.IsReady() {
					switch {
					// animation shows from earlier tick, animate
					case animate.Index > -1 && animate.Index < len(animate.Sprites)-1:
						animate.Index += 1
						animate.Timer.Start(animate.GetDuration())
					default:
						// last sprite reached
						if animate.Loop {
							animate.Index = 0
							animate.Timer.Start(animate.GetDuration())
						}

						if animationtype == components.Destruction {
							EntitiesToRemove = append(EntitiesToRemove, query.Entity())
						}
					}
				} else {
					animate.Timer.Update()
				}
			}
		}
	}

	for _, entity := range EntitiesToRemove {
		slog.Debug("remove collectible")
		system.World.RemoveEntity(entity)
	}

	return nil
}

func (system *AnimationSystem) Draw(screen *ebiten.Image) {
	// write animations (these are no tiles!)
	op := &ebiten.DrawImageOptions{}
	query := system.Selector.Query(system.World)

	for query.Next() {
		pos, render := query.Get()

		for _, animate := range render.Animations() {
			if animate.Active {
				op.GeoM.Reset()
				op.GeoM.Translate(float64(pos.X), float64(pos.Y))
				sprite := animate.GetSprite()
				screen.DrawImage(sprite, op)
			}
		}
	}
}
