# -*- coding: utf-8 -*-
"""
NUD 自定义语法库：math 数学库
==============================
放 lib/ 目录，NUD 里：
    /being/
    import math
    a=10
    a^2          ← a 的平方：100
    a*2          ← a 乘 2：20
    a/2          ← a 除以 2：5
    [a%@]        ← a 除以 2 的余数：0
    |a|          ← a 的绝对值：10

支持写法（数学符号或中文都可以）：
  平方：  a^2 / a的平方
  乘法：  a*2 / a乘以2
  除法：  a/2 / a除以2
  余数：  a%2 / a%@2 / [a%2] / [a%@2] / [a%@] / a除以2的余数（%@ 后不写数字默认 2）
  绝对值：|a| / a的绝对值
"""
import re

LIB_NAME = "math"
LIB_VERSION = "1.0.0"
LIB_DESCRIPTION = "数学库：平方 ^、乘法 *、除法 /、余数 %@、绝对值 | |"

_NAME = r'[一-龥A-Za-z_][一-龥A-Za-z0-9_]*'

# 数学符号写法
_POW_RE = re.compile(r'^(' + _NAME + r')\s*\^\s*(-?\d+)$')   # 支持负数指数（Bug 14）
_MUL_RE = re.compile(r'^(' + _NAME + r')\s*\*\s*(\d+)$')
_DIV_RE = re.compile(r'^(' + _NAME + r')\s*/\s*(\d+)$')
_MOD_RE = re.compile(r'^\[?(' + _NAME + r')\s*(?:%@|%)\s*(\d+)?\]?$')
_ABS_RE = re.compile(r'^\|(' + _NAME + r')\|$')

# 中文写法
_CN_POW_RE = re.compile(r'^(' + _NAME + r')的平方$')
_CN_MUL_RE = re.compile(r'^(' + _NAME + r')乘以(\d+)$')
_CN_DIV_RE = re.compile(r'^(' + _NAME + r')除以(\d+)$')
_CN_MOD_RE = re.compile(r'^(' + _NAME + r')除以(\d+)的余数$')
_CN_ABS_RE = re.compile(r'^(' + _NAME + r')的绝对值$')


def parse_line(content, line_num, sm_imported):
    content = content.strip()
    if not content:
        return None, None
    op = None
    var = None
    n = None

    m = _POW_RE.match(content)
    if m:
        op, var, n = 'pow', m.group(1), int(m.group(2))
    if op is None:
        m = _CN_POW_RE.match(content)
        if m:
            op, var, n = 'pow', m.group(1), 2
    if op is None:
        m = _MUL_RE.match(content)
        if m:
            op, var, n = 'mul', m.group(1), float(m.group(2))
    if op is None:
        m = _CN_MUL_RE.match(content)
        if m:
            op, var, n = 'mul', m.group(1), float(m.group(2))
    if op is None:
        m = _DIV_RE.match(content)
        if m:
            op, var, n = 'div', m.group(1), float(m.group(2))
    if op is None:
        m = _CN_DIV_RE.match(content)
        if m:
            op, var, n = 'div', m.group(1), float(m.group(2))
    if op is None:
        m = _MOD_RE.match(content)
        if m:
            op, var = 'mod', m.group(1)
            n = int(m.group(2)) if m.group(2) else 2   # %@ 后不写数字默认 2
    if op is None:
        m = _CN_MOD_RE.match(content)
        if m:
            op, var, n = 'mod', m.group(1), int(m.group(2))
    if op is None:
        m = _ABS_RE.match(content)
        if m:
            op, var = 'abs', m.group(1)
    if op is None:
        m = _CN_ABS_RE.match(content)
        if m:
            op, var = 'abs', m.group(1)

    if op is None:
        return None, None
    return {'type': 'MATH_CALC', 'line': line_num, 'op': op, 'var': var, 'n': n}, None


def execute(node, env, registry, moves, output=None):
    op = getattr(node, 'op', '')
    var = getattr(node, 'var', '')
    n = getattr(node, 'n', 2)
    if var not in env:
        return f"找不到变量 '{var}'（先赋值再计算）"
    try:
        v = float(env[var])
    except (TypeError, ValueError):
        return f"变量 '{var}' 不是数字，没法算"

    if op == 'pow':
        result = v ** n          # 负数指数也支持（Bug 14）
    elif op == 'mul':
        result = v * n
    elif op == 'div':
        if n == 0:
            return '除数不能为 0'   # Bug 12
        result = v / n
    elif op == 'mod':
        if int(n) == 0:
            return '取余数不能为 0'  # Bug 13
        result = int(v) % int(n)
    elif op == 'abs':
        result = abs(v)
    else:
        return None

    # 结果尽量显示成整数
    text = str(int(result)) if float(result).is_integer() else str(round(result, 6))
    if output is not None:
        output.append((text, None))
    cb = env.get('_print_cb')
    if callable(cb):
        try:
            cb(text, None)
        except Exception:
            pass
    return None
