package main

import (
	"math"
	"math/rand"
	"github.com/gen2brain/raylib-go/raylib"
)

type ContourLayer struct {
	field  Field
	actors []*Actor
	rng    *rand.Rand
}

func NewContourLayer(sketch *Sketch, rng *rand.Rand, field Field) *ContourLayer {

	actors := make([]*Actor, 0)

	layer := ContourLayer {
		rng: rng,
		field: field,
		actors: actors,
	}

	layer.AddActors(1, sketch.sourceWidth, sketch.sourceHeight)

	return &layer
}

func (s *ContourLayer) AddActors(n, sourceWidth, sourceHeight int32) {
	for range n {
		x := s.rng.Int31() % sourceWidth
		y := s.rng.Int31() % sourceHeight
		newActor :=
			&Actor {
				position: rl.Vector2{X: float32(x), Y: float32(y)},
				field:    s.field,
				stepSize: 1,
				color:    rl.NewColor(11, 35, 176, 50),
			}
		s.actors = append(s.actors, newActor)
	}
}

func (s *ContourLayer) Update(ctx *RenderCtx) {
	s.AddActors(100, ctx.SourceWidth, ctx.SourceHeight)
}

func (s *ContourLayer) Draw(ctx *RenderCtx) {
	rl.BeginBlendMode(rl.BlendAdditive)
	for _, actor := range s.actors {
		actor.Draw()
	}
	rl.EndBlendMode()
}

func (s *ContourLayer) IsDirty() bool {
	return true
}

type Actor struct {
	position rl.Vector2
	field    Field
	stepSize float32
	color    rl.Color
}

func (a *Actor) Draw() {
	v := a.field.Get(a.position.X, a.position.Y)
	rad := rl.Remap(v, 0, 1, 0, 3*math.Pi)
	nextPosition := rl.Vector2{X: a.position.X + a.stepSize*float32(math.Cos(float64(rad))), Y: a.position.Y + a.stepSize*float32(math.Sin(float64(rad)))}
	rl.DrawLineV(a.position, nextPosition, a.color)
	//fmt.Printf("position %v -> nextPosition %v \n", a.position, nextPosition)
	a.position = nextPosition
}

func RandRadialVec(rng *rand.Rand, minRadius float32, maxRadius float32, loAngle float32, hiAngle float32) rl.Vector2 {
	r := float64(rl.Remap(rng.Float32(), 0, 1, minRadius, maxRadius))
	deg := float64(rl.Remap(rng.Float32(), 0, 1, loAngle, hiAngle))
	rad := rl.Deg2rad * deg
	return rl.Vector2{X: float32(r * math.Cos(rad)), Y: float32(r * math.Sin(rad))}
}

type Worm struct {
	position   rl.Vector2
	angles     []float32
	angleIndex int
	stepSize   int
	renderPct  float32
}

func (w *Worm) Draw(ctx *RenderCtx) {
	rl.PushMatrix()
	rl.Translatef(w.position.X, w.position.Y, 0)
	lastAngle := float32(0.0)
	stepCount := 0
	nudged := false
	for i := range w.angles {
		ii := (i + w.angleIndex) % len(w.angles)
		angle := w.angles[ii]
		deltaAngle := angle - lastAngle
		if !nudged {
			rad := float64(deltaAngle * math.Pi / 180.0)
			nudge := rl.Vector2{X: float32(w.stepSize) * float32(math.Cos(rad)), Y: float32(w.stepSize) * float32(math.Sin(rad))}
			w.position = rl.Vector2Add(w.position, nudge)
			nudged = true
		}
		rl.Rotatef(deltaAngle, 0, 0, 1)
		rl.DrawLine(0, 0, int32(w.stepSize), 0, rl.NewColor(184, 187, 38, 50))
		rl.Translatef(float32(w.stepSize), 0, 0)
		lastAngle = angle
		stepCount++
		if stepCount > int(float32(len(w.angles))*w.renderPct) {
			break
		}
	}
	rl.PopMatrix()
	w.angleIndex = (w.angleIndex + 1) % len(w.angles)
}

