package systems

import (
	. "openquell/components"

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

type GridSystem struct {
	World                   *ecs.World
	Selector                *generic.Filter3[Renderable, Position, Solid]
	UseCache                bool
	Cache                   *ebiten.Image
	Count                   int // register tile count, invalidates cache
	Background              *ebiten.Image
	Width, Height, Tilesize int
}

func NewGridSystem(world *ecs.World, width, height,
	tilesize int, background *ebiten.Image) System {

	cache := ebiten.NewImage(width, height)

	system := &GridSystem{
		Selector:   generic.NewFilter3[Renderable, Position, Solid](),
		UseCache:   false,
		Cache:      cache,
		Width:      width,
		Height:     height,
		Tilesize:   tilesize,
		Background: background,
		World:      world,
	}

	return system
}

func (system *GridSystem) Update() error {
	return nil
}

func (system *GridSystem) Draw(screen *ebiten.Image) {
	op := &ebiten.DrawImageOptions{}
	query := system.Selector.Query(system.World)

	if !system.UseCache || query.Count() != system.Count {
		// map not cached or cacheable, write it to the cache
		system.Cache.DrawImage(system.Background, op)

		system.Count = query.Count()
		counter := 0
		for query.Next() {
			sprite, pos, _ := query.Get()

			counter++
			op.GeoM.Reset()
			op.GeoM.Translate(float64(pos.X), float64(pos.Y))
			system.Cache.DrawImage(sprite.Image, op)

		}

		op.GeoM.Reset()
		screen.DrawImage(system.Cache, op)

		system.UseCache = true

	} else {
		// use the cached map
		op.GeoM.Reset()
		screen.DrawImage(system.Cache, op)
		query.Close()
	}
}
