src/UI/NavStack.ps1

# NavStack — Stack tipado de frames de navegación.
#
# Encapsula System.Collections.Generic.Stack[object] con una API más explícita
# y guards en Pop/Peek para no devolver null silencioso.
#
# Cada "frame" es un hashtable opaco al stack — el caller decide su forma. En
# MainScreen son @{ Path; Repos; SelectedIndex; ViewportStart } pero NavStack
# no lo conoce ni le importa.
#
# Función ÚNICA: LIFO de frames. No conoce UI, no conoce filesystem.

class NavStack {
    hidden [System.Collections.Generic.Stack[object]] $Items

    NavStack() {
        $this.Items = [System.Collections.Generic.Stack[object]]::new()
    }

    [void] Push([object]$frame) {
        if ($null -eq $frame) {
            throw "NavStack.Push: frame no puede ser null."
        }
        $this.Items.Push($frame)
    }

    # Pop con guard explícito — Stack[object].Pop() tira InvalidOperationException
    # con mensaje en inglés genérico. Acá tiramos algo descriptivo.
    [object] Pop() {
        if ($this.Items.Count -eq 0) {
            throw "NavStack.Pop: el stack está vacío."
        }
        return $this.Items.Pop()
    }

    [object] Peek() {
        if ($this.Items.Count -eq 0) {
            throw "NavStack.Peek: el stack está vacío."
        }
        return $this.Items.Peek()
    }

    [int] Count() {
        return $this.Items.Count
    }

    [bool] IsEmpty() {
        return $this.Items.Count -eq 0
    }

    [void] Clear() {
        $this.Items.Clear()
    }
}