package game

import (
	"fmt"
	"image"
	. "openquell/components"
	. "openquell/config"

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

type PlayerSystem struct {
	World       *ecs.World
	Grid        *Grid
	Selector    *generic.Filter3[Position, Velocity, Player]
	Particle    *ParticleSystem
	Collectible *CollectibleSystem
}

func NewPlayerSystem(world *ecs.World) *PlayerSystem {

	system := &PlayerSystem{
		Selector: generic.NewFilter3[Position, Velocity, Player](),
	}

	return system
}

func (system PlayerSystem) Update() error {
	query := system.Selector.Query(system.World)

	var bumped bool
	var particle_pos image.Point

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

		if !velocity.Moving() {
			switch {
			case ebiten.IsKeyPressed(ebiten.KeyRight):
				velocity.Change(East)
			case ebiten.IsKeyPressed(ebiten.KeyLeft):
				velocity.Change(West)
			case ebiten.IsKeyPressed(ebiten.KeyDown):
				velocity.Change(South)
			case ebiten.IsKeyPressed(ebiten.KeyUp):
				velocity.Change(North)
				// other keys: <tab>: switch player, etc
			}
		}

		if velocity.Moving() {
			ok, newpos := system.Grid.BumpEdge(playerposition, velocity)
			if ok {
				fmt.Printf("falling off the edge, new pos: %v\n", newpos)
				playerposition.Set(newpos)
			} else {
				ok, tilepos := system.Grid.GetSolidNeighborPosition(playerposition, velocity, true)
				if ok {
					intersects, newpos := tilepos.Intersects(playerposition, velocity)
					if intersects {
						fmt.Printf("collision detected. tile: %s\n", tilepos)
						fmt.Printf("                  player: %s\n", playerposition)
						fmt.Printf("                     new: %s\n", newpos)

						playerposition.Set(newpos)
						fmt.Printf("              player new: %s\n", playerposition)
						velocity.Change(Stop)
					}
				}
			}

			bumped, particle_pos = system.Collectible.CheckPlayerCollision(playerposition, velocity)
		}

	}

	system.Particle.Update(bumped, &particle_pos)

	return nil
}
