package machine

import "tetris/game/state"

type Machine struct {
	current  state.Handler
	pending  string
	registry map[string]state.Handler
}

// New creates an empty machine.
func New() *Machine {
	return &Machine{registry: make(map[string]state.Handler)}
}

// Register binds a name to a factory that returns a fresh state.Handler.
func (m *Machine) Register(name string, handler state.Handler) {
	m.registry[name] = handler
}

// Start switches to the named initial state immediately (calls Enter()).
func (m *Machine) Start(name string) {
	m.switchNow(name)
}

// Switch queues a transition to be applied after the current Update finishes.
func (m *Machine) Switch(name string) {
	if name == "" || name == m.pending {
		return
	}
	m.pending = name
}

// Update ticks the current state, then applies any queued transition.
func (m *Machine) Update(delta float32) bool {
	if m.current == nil {
		return false
	}
	m.current.Update(m, delta)

	if m.pending != "" {
		if m.pending == "quit" {
			return false
		}
		next := m.pending
		m.pending = ""
		m.switchNow(next)
	}
	return true
}

// Render proxies to current state.
func (m *Machine) Render() {
	if m.current != nil {
		m.current.Render()
	}
}

func (m *Machine) switchNow(name string) {
	handler, ok := m.registry[name]
	if !ok {
		// Unknown state: dont switch.
		return
	}

	if m.current != nil {
		m.current.Exit()
	}

	m.current = handler
	m.current.Enter()
}
