package compiler

import (
	"c65gm/internal/preproc"
)

// CompilerContext holds all shared resources needed by commands during compilation
type CompilerContext struct {
	// Symbol table for variables and constants
	SymbolTable *SymbolTable

	// Function handler for FUNC/CALL/FEND commands
	FunctionHandler *FunctionHandler

	// Constant string handler
	ConstStrHandler *ConstantStringHandler

	// Label stacks for control flow
	LoopStartStack *LabelStack // Start of loop (like WHILE)
	LoopEndStack   *LabelStack // WHILE...WEND
	IfStack        *LabelStack // IF...ENDIF
	GeneralStack   *LabelStack // General purpose (GOSUB, etc)
	ForStack       *ForStack   // For loop stack

	// Pragma access for per-line pragma lookup
	Pragma *preproc.Pragma
}

// NewCompilerContext creates a new compiler context with initialized resources
func NewCompilerContext(pragma *preproc.Pragma) *CompilerContext {
	symTable := NewSymbolTable()
	constStrHandler := NewConstantStringHandler()
	generalStack := NewLabelStack("_L")

	ctx := &CompilerContext{
		SymbolTable:     symTable,
		ConstStrHandler: constStrHandler,
		LoopStartStack:  NewLabelStack("_LOOPSTART"),
		LoopEndStack:    NewLabelStack("_LOOPEND"),
		IfStack:         NewLabelStack("_I"),
		GeneralStack:    generalStack,
		ForStack:        NewForStack(),
		Pragma:          pragma,
	}

	// FunctionHandler needs references to other components
	ctx.FunctionHandler = NewFunctionHandler(symTable, generalStack, constStrHandler, pragma)

	return ctx
}

// CurrentScope returns the current function scope(s) for symbol resolution
func (ctx *CompilerContext) CurrentScope() []string {
	funcName := ctx.FunctionHandler.CurrentFunction()
	if funcName == "" {
		return nil
	}
	return []string{funcName}
}
