package gameelement

import (
	"math/rand/v2"
	"mover/elements"
	"mover/gamedata"

	"github.com/hajimehoshi/ebiten/v2"
)

type RainLayer struct {
	Sprite       *ebiten.Image
	lastInputs   gamedata.GameInputs
	raindrops    []*elements.RainDrop
	nextsplashes []gamedata.Coordinates
	rainsplashes []*elements.RainSplash
	dimensions   gamedata.Area
	cycle        int
}

func NewRainLayer(a gamedata.Area) *RainLayer {
	rl := &RainLayer{
		Sprite:     ebiten.NewImage(a.Width, a.Height),
		dimensions: a,
	}

	for i := 0; i < 50; i++ {
		nrd := elements.NewRainDrop()
		nrd.SetPosition(gamedata.Coordinates{X: rand.Float64() * float64(a.Width), Y: rand.Float64() * float64(a.Height)})
		rl.raindrops = append(rl.raindrops, nrd)
	}

	for i := 0; i < 50; i++ {
		nrd := elements.NewRainSplash()
		nrd.SetPosition(gamedata.Coordinates{X: rand.Float64() * float64(a.Width), Y: rand.Float64() * float64(a.Height)})
		rl.rainsplashes = append(rl.rainsplashes, nrd)
	}
	return rl
}

func (r *RainLayer) SetInputs(inputs gamedata.GameInputs) {
	r.lastInputs = inputs
}

func (r *RainLayer) Update() error {

	r.UpdateDrops()
	r.UpdateSplashes()

	r.cycle++
	return nil
}

func (r *RainLayer) Draw(drawimg *ebiten.Image) {
	r.Sprite.Clear()

	for _, drop := range r.raindrops {
		drop.Draw()

		op := &ebiten.DrawImageOptions{}
		op.GeoM.Translate(drop.GetPosition().X, drop.GetPosition().Y)
		op.ColorScale.ScaleAlpha(0.5)
		r.Sprite.DrawImage(drop.Sprite, op)
	}

	for _, drop := range r.rainsplashes {
		drop.Draw()

		op := &ebiten.DrawImageOptions{}
		op.GeoM.Translate(drop.GetPosition().X, drop.GetPosition().Y)
		op.ColorScale.ScaleAlpha(0.5)
		r.Sprite.DrawImage(drop.Sprite, op)
	}

	drawimg.DrawImage(r.Sprite, nil)

}

func (r *RainLayer) Initialize() {

}

func (r *RainLayer) RegisterEvents(e gamedata.GameEvent, f func()) {

}

func (r *RainLayer) UpdateDrops() {
	i := 0
	for _, drop := range r.raindrops {
		drop.Update()

		if !drop.Expired() {
			r.raindrops[i] = drop
			i++
		} else {
			r.nextsplashes = append(r.nextsplashes, drop.GetPosition())
		}
	}

	var j int = i
	var newdrops int = 0
	for ; j < len(r.raindrops); j++ {
		r.raindrops[j] = nil
	}
	newdrops = len(r.raindrops) - i
	r.raindrops = r.raindrops[:i]

	for k := 0; k < newdrops; k++ {
		nrd := elements.NewRainDrop()
		nrd.SetPosition(gamedata.Coordinates{X: rand.Float64() * float64(r.dimensions.Width), Y: rand.Float64() * float64(r.dimensions.Height)})
		r.raindrops = append(r.raindrops, nrd)
	}
}

func (r *RainLayer) UpdateSplashes() {
	i := 0
	for _, drop := range r.rainsplashes {
		drop.Update()

		if !drop.Expired() {
			r.rainsplashes[i] = drop
			i++
		}
	}

	var j int = i
	//var newdrops int = 0
	for ; j < len(r.rainsplashes); j++ {
		r.rainsplashes[j] = nil
	}
	//newdrops = len(r.rainsplashes) - i
	r.rainsplashes = r.rainsplashes[:i]

	/*
		for k := 0; k < newdrops; k++ {
			nrd := elements.NewRainSplash()
			nrd.SetPosition(gamedata.Coordinates{X: rand.Float64() * float64(r.dimensions.Width), Y: rand.Float64() * float64(r.dimensions.Height)})
			r.rainsplashes = append(r.rainsplashes, nrd)
		}*/

	for _, splashloc := range r.nextsplashes {
		nrd := elements.NewRainSplash()
		nrd.SetPosition(splashloc)
		r.rainsplashes = append(r.rainsplashes, nrd)
	}

	r.nextsplashes = r.nextsplashes[:0]

}
