package optimizer

import "strings"

// passImmElimination removes redundant immediate loads.
// Pattern: lda #N; ... (no A modification) ...; lda #N → remove second
// Applies to A, X, Y.
func passImmElimination(lines []asmLine) []asmLine {
	rs := newRegState()
	var result []asmLine

	for _, line := range lines {
		if !line.isCode {
			if line.isLabel {
				rs.reset()
			}
			result = append(result, line)
			continue
		}

		if isChainBreaker(line.opcode) {
			rs.reset()
			result = append(result, line)
			continue
		}

		if isRedundantImm(line, rs) {
			continue // remove line
		}

		updateRegState(line, rs)
		result = append(result, line)
	}

	return result
}

func isRedundantImm(line asmLine, rs *regState) bool {
	if !isImmediate(line.operand) {
		return false
	}
	val := parseValueAfterHash(line.operand)
	if val < 0 {
		return false // unparseable (label ref, <label, >label)
	}
	switch line.opcode {
	case "lda":
		if rs.a.val == val {
			return true
		}
		rs.loadImm("a", val)
	case "ldx":
		if rs.x.val == val {
			return true
		}
		rs.loadImm("x", val)
	case "ldy":
		if rs.y.val == val {
			return true
		}
		rs.loadImm("y", val)
	}
	return false
}

// parseValueAfterHash extracts the numeric value after '#'. Returns -1 for unparseable.
func parseValueAfterHash(operand string) int {
	if len(operand) < 2 {
		return -1
	}
	s := operand[1:]
	// ACME high/low byte operators are not evaluable at optimize time
	if strings.HasPrefix(s, "<") || strings.HasPrefix(s, ">") {
		return -1
	}
	return parseHexOrDec(s)
}
