package compiler

import "fmt"

// SwitchInfo stores information about a SWITCH statement
type SwitchInfo struct {
	SwitchOperand    *OperandInfo // The expression being switched on
	EndLabel         string       // Label for end of switch (_ENDSWITCH)
	NeedsPendingCode bool         // True if we need to emit implicit break + skip label
	PendingSkipLabel string       // The skip label that needs to be emitted
	HasDefault       bool         // True if DEFAULT has been encountered
	UseLongJump      bool         // Whether to use long jumps
}

// SwitchStack manages the stack of SWITCH contexts
type SwitchStack struct {
	stack []*SwitchInfo
}

// NewSwitchStack creates a new SwitchStack
func NewSwitchStack() *SwitchStack {
	return &SwitchStack{
		stack: make([]*SwitchInfo, 0),
	}
}

// Push adds a new SWITCH context to the stack
func (ss *SwitchStack) Push(info *SwitchInfo) {
	ss.stack = append(ss.stack, info)
}

// Peek returns the top SWITCH context without removing it
func (ss *SwitchStack) Peek() (*SwitchInfo, error) {
	if len(ss.stack) == 0 {
		return nil, fmt.Errorf("stack underflow: SWITCH stack is empty")
	}
	return ss.stack[len(ss.stack)-1], nil
}

// Pop removes and returns the top SWITCH context
func (ss *SwitchStack) Pop() (*SwitchInfo, error) {
	if len(ss.stack) == 0 {
		return nil, fmt.Errorf("stack underflow: SWITCH stack is empty")
	}
	info := ss.stack[len(ss.stack)-1]
	ss.stack = ss.stack[:len(ss.stack)-1]
	return info, nil
}

// IsEmpty returns true if the stack is empty
func (ss *SwitchStack) IsEmpty() bool {
	return len(ss.stack) == 0
}

// Size returns the number of items on the stack
func (ss *SwitchStack) Size() int {
	return len(ss.stack)
}
