from typing import (
    Optional,
    Union,
    Sequence,
    TYPE_CHECKING,
)

from debputy.linting.lint_util import LintState
from debputy.lsp.config.parser import DEBPUTY_CONFIG_PARSER
from debputy.lsp.lsp_features import (
    lint_diagnostics,
    lsp_standard_handler,
    lsp_hover,
    lsp_completer,
    LanguageDispatchRule,
    SecondaryLanguage,
)
from debputy.lsp.lsp_generic_yaml import (
    generic_yaml_hover,
    LSPYAMLHelper,
    generic_yaml_lint,
    generic_yaml_completer,
)

try:
    from debputy.lsp.debputy_ls import DebputyLanguageServer
    from debputy.lsp.vendoring._deb822_repro.locatable import (
        Position as TEPosition,
        Range as TERange,
    )
except ImportError:
    pass

if TYPE_CHECKING:
    import lsprotocol.types as types
else:
    import debputy.lsprotocol.types as types


_DISPATCH_RULE = LanguageDispatchRule.new_rule(
    "debputy-config.yaml",
    "debputy-config.yaml",
    [],
    [SecondaryLanguage("yaml", secondary_lookup="basename")],
)


lsp_standard_handler(_DISPATCH_RULE, types.TEXT_DOCUMENT_CODE_ACTION)
lsp_standard_handler(_DISPATCH_RULE, types.TEXT_DOCUMENT_WILL_SAVE_WAIT_UNTIL)


def _initialize_yaml_helper(lint_state: LintState) -> LSPYAMLHelper[None]:
    return LSPYAMLHelper(
        lint_state,
        lint_state.plugin_feature_set.manifest_parser_generator,
        None,
    )


@lint_diagnostics(_DISPATCH_RULE)
async def lint_debputy_config(lint_state: LintState) -> None:
    await generic_yaml_lint(
        lint_state,
        DEBPUTY_CONFIG_PARSER,
        _initialize_yaml_helper,
    )


@lsp_completer(_DISPATCH_RULE)
def deboputy_config_completer(
    ls: "DebputyLanguageServer",
    params: types.CompletionParams,
) -> Optional[Union[types.CompletionList, Sequence[types.CompletionItem]]]:
    return generic_yaml_completer(
        ls,
        params,
        DEBPUTY_CONFIG_PARSER,
    )


@lsp_hover(_DISPATCH_RULE)
def debputy_config_hover(
    ls: "DebputyLanguageServer",
    params: types.HoverParams,
) -> Optional[types.Hover]:
    return generic_yaml_hover(ls, params, lambda _: DEBPUTY_CONFIG_PARSER)
