package main

import (
	"fmt"
	"math/rand"
	"red-green/door"
	"strings"
	"time"

	"github.com/seehuhn/mt19937"
)

type StarPos struct {
	Y      int
	X      int
	Symbol int
	Color  bool
}

type StarField struct {
	RNG *rand.Rand
	MX  int
	MY  int
	Sky map[StarPos]bool
}

func (s *StarField) make_pos() StarPos {
	for {
		pos := StarPos{X: s.RNG.Intn(s.MX), Y: s.RNG.Intn(s.MY)}
		_, found := (*s).Sky[pos]
		if !found {
			return pos
		}
	}
}

func (s *StarField) Regenerate() {
	s.MX = door.Width
	s.MY = door.Height
	s.Sky = make(map[StarPos]bool)

	s.RNG = rand.New(mt19937.New())
	s.RNG.Seed(time.Now().UnixNano())

	max_stars := ((s.MX * s.MY) / 40)
	for i := 0; i < max_stars; i++ {
		pos := s.make_pos()
		pos.Symbol = i % 2
		pos.Color = i%5 < 2
		s.Sky[pos] = true
	}
}

func (s *StarField) Display(d *door.Door) {
	white := door.ColorText("WHITE")
	dark := door.ColorText("BOLD BLACK")

	d.Write(door.Reset + door.Clrscr)
	var stars [2]string
	stars[0] = "."
	if door.Unicode {
		stars[1] = "\u2219"
	} else {
		stars[1] = "\xf9"
	}

	var i int = 0
	var last_pos StarPos

	for pos, _ := range s.Sky {
		use_goto := true

		if i != 0 {
			if pos.Y == last_pos.Y {
				dx := pos.X - last_pos.X
				if dx <= 0 {
					use_goto = false
				} else {
					if dx < 5 {
						d.Write(strings.Repeat(" ", dx))
						use_goto = false
					} else {
						d.Write(fmt.Sprintf("\x1b[%dC", dx))
						use_goto = false
					}
				}
			}
		}

		if use_goto {
			d.Write(door.Goto(pos.X, pos.Y))
		}

		if pos.Color {
			d.Write(dark)
		} else {
			d.Write(white)
		}
		d.Write(stars[pos.Symbol])
		last_pos = pos
		last_pos.X++
		i++
	}
}