"""Marking — Convert k-OA to SOA over Σ^(k) (Definition 4.4, arXiv 1004.2372)."""

from .soa import SOA
from .grammar import Symbol, Epsilon, Empty, Plus, Star, Optional, Concat, Alt


def mark_koa(G):
    """
    Mark a k-OA G as a SOA over Σ^(k).

    Process nodes in arbitrary order. For the i-th occurrence of label a,
    replace by a^(i) (represented as Symbol('a_i')).

    Returns a SOA H over Σ^(k) such that L(G) = strip(L(H)).
    """
    H = SOA()
    H.src = G.src
    H.sink = G.sink
    H._succ = {n: set(succ) for n, succ in G._succ.items()}
    H._pred = {n: set(pred) for n, pred in G._pred.items()}
    H._label = {}
    H._next = G._next

    counts = {}
    for n in G._succ:
        lab = G._label.get(n)
        if lab is not None and not isinstance(lab, (Empty, Epsilon)) and n not in (G.src, G.sink):
            sym = strip_k(lab)
            key = sym.value if isinstance(sym, Symbol) else str(sym)
            counts[key] = counts.get(key, 0) + 1
            H._label[n] = Symbol(f"{key}_{counts[key]}")
        elif n in (G.src, G.sink):
            H._label[n] = None
        else:
            H._label[n] = lab

    return H


def strip_k(node):
    """Remove k-ORE markers from AST: Symbol('a_1') → Symbol('a'), Symbol('b^(2)') → Symbol('b')."""
    if isinstance(node, Symbol):
        import re
        value = node.value
        value = re.sub(r'_\d+$', '', value)
        value = re.sub(r'\^\(\d+\)$', '', value)
        return Symbol(value)
    if isinstance(node, (Epsilon, Empty)):
        return node
    if isinstance(node, (Plus, Optional, Star)):
        return type(node)(strip_k(node.child))
    if isinstance(node, (Concat, Alt)):
        return type(node)([strip_k(child) for child in node.parts])
    return node
