package compiler

import "c65gm/internal/preproc"

const (
	asmStringDeclStart    = " !raw "
	asmStringDeclEnd      = " !8 0"
	asmCBMStringDeclStart = " !pet "
	asmCBMStringDeclEnd   = " !8 0"
)

type ConstantString struct {
	label         string
	value         string
	compressable  bool
	useCBMStrings bool
}

type ConstantStringHandler struct {
	strings     []*ConstantString
	compressMap map[string]string
}

func NewConstantStringHandler() *ConstantStringHandler {
	return &ConstantStringHandler{
		strings:     make([]*ConstantString, 0),
		compressMap: make(map[string]string),
	}
}

func (h *ConstantStringHandler) AddConstStr(label, value string, compress bool, ps preproc.PragmaSet) string {
	useCBM := ps.GetPragma("_P_USE_CBM_STRINGS") != "" && ps.GetPragma("_P_USE_CBM_STRINGS") != "0"

	if compress {
		if existingLabel, exists := h.compressMap[value]; exists {
			return existingLabel
		}
	}

	cs := &ConstantString{
		label:         label,
		value:         value,
		compressable:  compress,
		useCBMStrings: useCBM,
	}

	h.strings = append(h.strings, cs)

	if compress {
		h.compressMap[value] = label
	}

	return label
}

func (h *ConstantStringHandler) GenerateConstStrDecls() []string {
	result := make([]string, 0, len(h.strings)*3)

	for _, cs := range h.strings {
		startStr := asmStringDeclStart
		endStr := asmStringDeclEnd

		if cs.useCBMStrings {
			startStr = asmCBMStringDeclStart
			endStr = asmCBMStringDeclEnd
		}

		result = append(result, cs.label)
		result = append(result, startStr+cs.value)
		result = append(result, endStr)
	}

	return result
}
