import dataclasses
from typing import TypedDict, TYPE_CHECKING
from collections.abc import Callable

from debputy.plugin.plugin_state import current_debputy_plugin_required

if TYPE_CHECKING:
    from debputy.manifest_parser.parser_data import ParserContextData
    from debputy.manifest_parser.util import AttributePath


class DebputyParsedContent(TypedDict):
    pass


class DebputyDispatchableType:
    __slots__ = ("_debputy_plugin",)

    def __init__(self) -> None:
        self._debputy_plugin = current_debputy_plugin_required()


@dataclasses.dataclass
class TypeMapping[S: (int, str, int | str), T]:
    target_type: type[T]
    source_type: type[S]
    mapper: Callable[[S, "AttributePath", "ParserContextData | None"], T]
    lint_validator: Callable[[S, "AttributePath"], None] | None = None

    def with_mapper_as_lint_validator(self) -> "TypeMapping[S, T]":
        def _lint_validator(value: S, attribute_path: "AttributePath") -> None:
            self.mapper(value, attribute_path, None)

        return TypeMapping(
            self.target_type,
            self.source_type,
            self.mapper,
            _lint_validator,
        )
