package systems

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

	. "openquell/config"
	"openquell/observers"

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

type CollectibleSystem struct {
	World    *ecs.World
	Cellsize int
	Selector *generic.Filter3[Position, Collectible, Renderable]
}

func NewCollectibleSystem(world *ecs.World, cellsize int) System {
	system := &CollectibleSystem{
		Selector: generic.NewFilter3[Position, Collectible, Renderable](),
		World:    world,
		Cellsize: cellsize,
	}

	return system
}

func (system *CollectibleSystem) Update() error {
	observer := observers.GetGameObserver(system.World)

	posID := ecs.ComponentID[components.Position](system.World)
	veloID := ecs.ComponentID[components.Velocity](system.World)

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

	if numcollectibles == 0 || observer.Lost {
		slog.Debug("WON")
		timer := observers.GetGameObserver(system.World).StopTimer
		if !timer.Running {
			timer.Start(LEVEL_END_WAIT)

		}
		query.Close()
		return nil
	}

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

		for _, player := range observer.GetPlayers() {
			if !system.World.Alive(player) {
				continue
			}

			playerposition := (*Position)(system.World.Get(player, posID))
			playervelocity := (*Velocity)(system.World.Get(player, veloID))

			ok, _ := colposition.Intersects(playerposition, playervelocity)
			if ok && !collectible.Hit {
				slog.Debug("bumped into collectible", "colpos", colposition)

				render.StartAnimation(components.Destruction)

				// position the animation relative to the middle of the current entity
				colposition.Update(
					colposition.X-(system.Cellsize/2),
					colposition.Y-(system.Cellsize/2),
					64,
				)

				collectible.Hit = true
				numcollectibles--
			}
		}
	}

	return nil
}

func (system *CollectibleSystem) Draw(screen *ebiten.Image) {
	// write the movable tiles
	op := &ebiten.DrawImageOptions{}
	query := system.Selector.Query(system.World)

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

		if !sprite.Hidden {
			op.GeoM.Reset()
			op.GeoM.Translate(float64(pos.X), float64(pos.Y))

			screen.DrawImage(sprite.Image, op)
		}
	}
}
