"""viper.languages — Unified multi-language code parsing.

Public API
----------
- ``guess_language(filename)`` — guess language from file extension
- ``get_parser(lang)``         — obtain a ``LanguageParser`` instance
- ``parse(code, lang)``        — shortcut: parse code and return functions

Registry
--------
Language parsers self-register via ``register_language()``.  To add a new
language, create a sub-module and call ``register_language()`` at import time.
"""

from __future__ import annotations

import os
from typing import Any

from viper.languages.base import Function, LanguageParser, ParsingEngine, TreeSitterParser

# ---------------------------------------------------------------------------
# Registry
# ---------------------------------------------------------------------------

_registry: dict[str, type[LanguageParser]] = {}
_extension_map: dict[str, str] = {}  # ".c" → "c"


def register_language(parser_cls: type[LanguageParser]) -> None:
    """Register a parser class for its declared language name and extensions."""
    lang = parser_cls.language_name
    _registry[lang] = parser_cls
    for ext in parser_cls.file_extensions:
        _extension_map[ext.lower()] = lang


def guess_language(filename: str) -> str:
    """Guess the programming language from a file extension.

    Raises ``ValueError`` if the extension is not recognised.
    """
    ext = os.path.splitext(filename)[1].lower()
    lang = _extension_map.get(ext)
    if lang is None:
        raise ValueError(f"Unsupported file extension: {ext}")
    return lang


def get_parser(lang: str) -> LanguageParser:
    """Return a parser instance for the given *lang* identifier.

    Raises ``ValueError`` if no parser is registered for *lang*.
    """
    parser_cls = _registry.get(lang)
    if parser_cls is None:
        raise ValueError(f"Unsupported language: {lang}")
    return parser_cls()


def parse(code: bytes, lang: str) -> list[Function]:
    """Parse *code* as *lang* and return the extracted function definitions."""
    parser = get_parser(lang)
    return parser.get_function_definitions(code)


# ---------------------------------------------------------------------------
# Auto-register built-in languages on import
# ---------------------------------------------------------------------------

from viper.languages.c import CTreeSitterParser  # noqa: E402
from viper.languages.cpp import CppTreeSitterParser  # noqa: E402
from viper.languages.python import PythonTreeSitterParser  # noqa: E402
from viper.languages.systemverilog import SystemVerilogTreeSitterParser  # noqa: E402

register_language(CTreeSitterParser)
register_language(CppTreeSitterParser)
register_language(PythonTreeSitterParser)
register_language(SystemVerilogTreeSitterParser)

__all__ = [
    "Function",
    "LanguageParser",
    "ParsingEngine",
    "TreeSitterParser",
    "guess_language",
    "get_parser",
    "parse",
    "register_language",
    "CTreeSitterParser",
    "CppTreeSitterParser",
    "PythonTreeSitterParser",
    "SystemVerilogTreeSitterParser",
]
