"""
CSSL Bridge - Python API for CSSL Language
Provides CsslLang class for executing CSSL code from Python.
"""

import threading
from pathlib import Path
from typing import Any, List, Optional, Callable


class CsslLang:
    """
    CSSL Language interface for Python.

    Usage:
        from includecpp import CSSL
        cssl = CSSL.CsslLang()
        result = cssl.exec("script.cssl", arg1, arg2)
        cssl.T_exec("async_script.cssl", arg1)  # Threaded
    """

    def __init__(self, output_callback: Optional[Callable[[str, str], None]] = None):
        """
        Initialize CSSL runtime.

        Args:
            output_callback: Optional callback for output (text, level)
        """
        self._output_callback = output_callback
        self._runtime = None
        self._threads: List[threading.Thread] = []

    def _get_runtime(self):
        """Lazy load CSSL runtime."""
        if self._runtime is None:
            from .cssl import CSSLRuntime
            self._runtime = CSSLRuntime(output_callback=self._output_callback)
        return self._runtime

    def exec(self, path_or_code: str, *args) -> Any:
        """
        Execute CSSL code or file.

        Args:
            path_or_code: Path to .cssl file or CSSL code string
            *args: Arguments to pass to the script

        Returns:
            Execution result
        """
        runtime = self._get_runtime()

        # Check if it's a file path
        path = Path(path_or_code)
        if path.exists() and path.suffix in ('.cssl', '.cssl-mod'):
            source = path.read_text(encoding='utf-8')
        else:
            source = path_or_code

        # Set arguments in runtime scope
        runtime.global_scope.set('args', list(args))
        runtime.global_scope.set('argc', len(args))

        # Execute as standalone program
        try:
            result = runtime.execute_program(source)
            return result
        except Exception as e:
            raise RuntimeError(f"CSSL Error: {e}") from e

    def T_exec(self, path_or_code: str, *args, callback: Optional[Callable[[Any], None]] = None) -> threading.Thread:
        """
        Execute CSSL code asynchronously in a thread.

        Args:
            path_or_code: Path to .cssl file or CSSL code string
            *args: Arguments to pass to the script
            callback: Optional callback when execution completes

        Returns:
            Thread object
        """
        def _run():
            try:
                result = self.exec(path_or_code, *args)
                if callback:
                    callback(result)
            except Exception as e:
                if callback:
                    callback(e)

        thread = threading.Thread(target=_run, daemon=True)
        thread.start()
        self._threads.append(thread)
        return thread

    def wait_all(self, timeout: Optional[float] = None):
        """Wait for all async executions to complete."""
        for thread in self._threads:
            thread.join(timeout=timeout)
        self._threads.clear()

    def get_output(self) -> List[str]:
        """Get output buffer from last execution."""
        runtime = self._get_runtime()
        return list(runtime.output_buffer)

    def clear_output(self):
        """Clear output buffer."""
        runtime = self._get_runtime()
        runtime.output_buffer.clear()

    def set_global(self, name: str, value: Any):
        """Set a global variable in CSSL runtime."""
        runtime = self._get_runtime()
        runtime.global_scope.set(name, value)

    def get_global(self, name: str) -> Any:
        """Get a global variable from CSSL runtime."""
        runtime = self._get_runtime()
        return runtime.global_scope.get(name)


# Singleton for convenience
_default_instance: Optional[CsslLang] = None

def get_cssl() -> CsslLang:
    """Get default CSSL instance."""
    global _default_instance
    if _default_instance is None:
        _default_instance = CsslLang()
    return _default_instance


# Module-level convenience functions
def exec(path_or_code: str, *args) -> Any:
    """
    Execute CSSL code or file.

    Usage:
        from includecpp import CSSL
        CSSL.exec("script.cssl", arg1, arg2)
        CSSL.exec("printl('Hello World');")

    Args:
        path_or_code: Path to .cssl file or CSSL code string
        *args: Arguments to pass to the script

    Returns:
        Execution result
    """
    return get_cssl().exec(path_or_code, *args)


def T_exec(path_or_code: str, *args, callback: Optional[Callable[[Any], None]] = None) -> threading.Thread:
    """
    Execute CSSL code asynchronously in a thread.

    Usage:
        from includecpp import CSSL
        CSSL.T_exec("async_script.cssl", arg1, callback=on_done)

    Args:
        path_or_code: Path to .cssl file or CSSL code string
        *args: Arguments to pass to the script
        callback: Optional callback when execution completes

    Returns:
        Thread object
    """
    return get_cssl().T_exec(path_or_code, *args, callback=callback)


def set_global(name: str, value: Any) -> None:
    """Set a global variable in CSSL runtime."""
    get_cssl().set_global(name, value)


def get_global(name: str) -> Any:
    """Get a global variable from CSSL runtime."""
    return get_cssl().get_global(name)


def get_output() -> List[str]:
    """Get output buffer from last execution."""
    return get_cssl().get_output()


def clear_output() -> None:
    """Clear output buffer."""
    get_cssl().clear_output()


# Aliases to avoid conflict with Python builtin exec
_exec = exec
_T_exec = T_exec

# Export all
__all__ = [
    'CsslLang',
    'get_cssl',
    'exec',
    '_exec',  # Alias for exec (avoids Python builtin conflict)
    'T_exec',
    '_T_exec',  # Alias for T_exec
    'set_global',
    'get_global',
    'get_output',
    'clear_output',
]
