package gameelement

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

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

type CloudLayer struct {
	Sprite     *ebiten.Image
	clouds     []*elements.Cloud
	dimensions gamedata.Area
	cycle      int
}

func NewCloudLayer(a gamedata.Area) *CloudLayer {
	c := &CloudLayer{
		Sprite:     ebiten.NewImage(a.Width, a.Height),
		cycle:      0,
		dimensions: a,
	}
	return c
}

func (c *CloudLayer) SetInputs(gamedata.GameInputs) {
}

func (c *CloudLayer) Update() error {
	c.cycle++

	for _, cloud := range c.clouds {
		cloud.Update()

		cpos := cloud.GetPosition()
		if cpos.X > float64(c.dimensions.Width)+float64(cloud.Sprite.Bounds().Dx()) {
			dx := -float64(cloud.Sprite.Bounds().Dx())
			cloud.SetPosition(gamedata.Coordinates{X: dx, Y: cloud.GetPosition().Y})
		}
		if cpos.X < -float64(cloud.Sprite.Bounds().Dx()) {
			dx := float64(c.dimensions.Width + cloud.Sprite.Bounds().Dx())
			cloud.SetPosition(gamedata.Coordinates{X: dx, Y: cloud.GetPosition().Y})
		}
		if cpos.Y > float64(c.dimensions.Height)+float64(cloud.Sprite.Bounds().Dy()) {
			dy := -float64(cloud.Sprite.Bounds().Dy())
			cloud.SetPosition(gamedata.Coordinates{X: cloud.GetPosition().X, Y: dy})
		}
		if cpos.Y < -float64(cloud.Sprite.Bounds().Dy()) {
			dy := float64(c.dimensions.Height + cloud.Sprite.Bounds().Dy())
			cloud.SetPosition(gamedata.Coordinates{X: cloud.GetPosition().X, Y: dy})
		}
	}

	return nil
}

func (c *CloudLayer) Draw(drawimg *ebiten.Image) {
	c.Sprite.Clear()

	for _, cloud := range c.clouds {
		cloud.Draw()
		op := &ebiten.DrawImageOptions{}
		op.GeoM.Translate(cloud.GetPosition().X, cloud.GetPosition().Y)
		op.ColorScale.ScaleAlpha(float32(cloud.Alpha))
		c.Sprite.DrawImage(cloud.Sprite, op)
	}

	drawimg.DrawImage(c.Sprite, nil)
}

func (c *CloudLayer) Initialize() {

	//cull previous cloud layer
	for i := 0; i < len(c.clouds); i++ {
		c.clouds[i] = nil
	}
	c.clouds = c.clouds[:0]

	numclouds := rand.IntN(20)
	angle := rand.Float64() * math.Pi * 2

	for i := 0; i < numclouds; i++ {

		a := gamedata.Area{
			Height: rand.IntN(c.dimensions.Width/2) + 1,
			Width:  rand.IntN(c.dimensions.Height/2) + 1,
		}

		velocity := rand.Float64() * 3
		//velocity := 0.

		newcloud := elements.NewCloud(a, angle, velocity)

		newcloud.Alpha = rand.Float64() / 2

		newcloud.SetPosition(gamedata.Coordinates{
			X: rand.Float64() * float64(c.dimensions.Width),
			Y: rand.Float64() * float64(c.dimensions.Height),
		})

		c.clouds = append(c.clouds, newcloud)
	}
}

func (c *CloudLayer) RegisterEvents(e gamedata.GameEvent, f func()) {

}
