import re

LIB_NAME = "move"
LIB_VERSION = "1.0.0"
LIB_DESCRIPTION = "按钮移动语法库，支持瞬移和平滑滑动"

_MOVE_RE = re.compile(
    r'^/m/([a-zA-Z一-龥][a-zA-Z0-9一-龥_]*)/x\s*=\s*(-?\d+|[a-zA-Z一-龥_][a-zA-Z0-9一-龥_]*)\s*/\s*y\s*=\s*(-?\d+|[a-zA-Z一-龥_][a-zA-Z0-9一-龥_]*)\s*$'
)

_SM_MOVE_RE = re.compile(
    r'^sm:/m/([a-zA-Z一-龥][a-zA-Z0-9一-龥_]*)/x\s*=\s*(-?\d+|[a-zA-Z一-龥_][a-zA-Z0-9一-龥_]*)\s*/\s*y\s*=\s*(-?\d+|[a-zA-Z一-龥_][a-zA-Z0-9一-龥_]*)\s*$'
)

X_MIN, X_MAX = -240, 240
Y_MIN, Y_MAX = -180, 180

MOVE = 'MOVE'

_parser = None
_executor = None


def _clamp(v: int, lo: int, hi: int) -> int:
    return max(lo, min(hi, v))


def parse_line(content: str, line_num: int, sm_imported: bool):
    if content.startswith('sm:/m/'):
        m = _SM_MOVE_RE.match(content)
        if m:
            if not sm_imported:
                return None, f'sm 滑动语法需要先 import sm（在第 {line_num} 行之前加一行 import sm）'
            return {
                'type': MOVE,
                'line': line_num,
                'name': m.group(1),
                'x': _coord_node(m.group(2)),
                'y': _coord_node(m.group(3)),
                'smooth': True,
            }, None
        return None, f'滑动语法写错了: {content}（正确写法: sm:/m/名字/x=N/y=M）'

    if content.startswith('/m/'):
        m = _MOVE_RE.match(content)
        if m:
            return {
                'type': MOVE,
                'line': line_num,
                'name': m.group(1),
                'x': _coord_node(m.group(2)),
                'y': _coord_node(m.group(3)),
                'smooth': False,
            }, None
        return None, f'移动语法写错了: {content}（正确写法: /m/名字/x=N/y=M）'

    return None, None


def _coord_node(raw):

    s = str(raw).strip()
    try:
        return int(float(s))
    except ValueError:
        return s


def _coord(raw, env=None):

    if isinstance(raw, (int, float)):
        return int(raw)
    s = str(raw).strip()
    try:
        return int(float(s))
    except ValueError:
        pass
    if env is not None and s in env:
        try:
            return int(float(env[s]))
        except (TypeError, ValueError):
            return 0
    return 0


def execute(node, env, registry, moves, output=None):
    name = getattr(node, 'name', node.get('name', '')) if isinstance(node, dict) else node.name
    x = _clamp(_coord(getattr(node, 'x', node.get('x', 0)) if isinstance(node, dict) else node.x, env), X_MIN, X_MAX)
    y = _clamp(_coord(getattr(node, 'y', node.get('y', 0)) if isinstance(node, dict) else node.y, env), Y_MIN, Y_MAX)
    smooth = getattr(node, 'smooth', node.get('smooth', False)) if isinstance(node, dict) else node.smooth
    duration = getattr(node, 'duration', node.get('duration', None)) if isinstance(node, dict) else getattr(node, 'duration', None)

    for b in registry:
        if b.get('name') == name:
            if not smooth:
                b['x'] = x
                b['y'] = y
            else:
                moves.append({'name': name, 'x': x, 'y': y, 'smooth': True,
                              'duration': duration})
            return None

    return f"找不到名为 '{name}' 的按钮，无法移动"


def register(parser_func, executor_func):
    global _parser, _executor
    _parser = parser_func
    _executor = executor_func


def get_parser():
    return _parser or parse_line


def get_executor():
    return _executor or execute
