# -*- coding: utf-8 -*-
#
# numerus - Public API
# This file provides the "Integration" layer for using Numerus in Python.
#

import os
from ._core import (
    NumerusVM, 
    parse_numerus_program, 
    NumerusError,
    OpCode,
    Instruction
)

__all__ = [
    "run_numerus_string", 
    "run_numerus_file", 
    "NumerusVM", 
    "parse_numerus_program", 
    "NumerusError",
    "OpCode",
    "Instruction"
]

def run_numerus_string(code_string: str) -> str:
    """
    Parses and executes a string of Numerus code.

    Args:
        code_string (str): The raw Numerus code (e.g., "10 72 31 33").

    Returns:
        str: The standard output generated by the program.
    
    Raises:
        NumerusError: If parsing or execution fails.
    """
    try:
        instructions = parse_numerus_program(code_string)
        vm = NumerusVM(instructions)
        output = vm.run()
        return output
    except Exception as e:
        # Re-raise as NumerusError if not already
        if not isinstance(e, NumerusError):
            raise NumerusError(f"Failed to run string: {e}")
        raise e

def run_numerus_file(filepath: str) -> str:
    """
    Loads, parses, and executes a .nm file from disk.

    Args:
        filepath (str): The path to the .nm file.

    Returns:
        str: The standard output generated by the program.

    Raises:
        FileNotFoundError: If the file does not exist.
        NumerusError: If parsing or execution fails.
    """
    try:
        with open(filepath, 'r', encoding='utf-8') as f:
            raw_content = f.read()
    except FileNotFoundError:
        raise FileNotFoundError(f"Numerus file not found at path: {filepath}")
    except Exception as e:
        raise NumerusError(f"Error reading file {filepath}: {e}")

    # Normalize whitespace (same as CLI)
    code_string = " ".join(raw_content.split())
    return run_numerus_string(code_string)