# Copyright 2017-2020 Palantir Technologies, Inc.
# Copyright 2021- Python Language Server Contributors.

import logging

from pylsp import _utils, hookimpl

log = logging.getLogger(__name__)


@hookimpl
def pylsp_hover(config, document, position):
    code_position = _utils.position_to_jedi_linecolumn(document, position)
    definitions = document.jedi_script(use_document_path=True).infer(**code_position)
    word = document.word_at_position(position)

    # Find first exact matching definition
    definition = next((x for x in definitions if x.name == word), None)

    # Ensure a definition is used if only one is available
    # even if the word doesn't match. An example of this case is 'np'
    # where 'numpy' doesn't match with 'np'. Same for NumPy ufuncs
    if len(definitions) == 1:
        definition = definitions[0]

    if not definition:
        return {"contents": ""}

    hover_capabilities = config.capabilities.get("textDocument", {}).get("hover", {})
    supported_markup_kinds = hover_capabilities.get("contentFormat", ["markdown"])
    preferred_markup_kind = _utils.choose_markup_kind(supported_markup_kinds)

    # Find first exact matching signature
    signature = next(
        (
            x.to_string()
            for x in definition.get_signatures()
            if (x.name == word and x.type not in ["module"])
        ),
        "",
    )

    return {
        "contents": _utils.format_docstring(
            # raw docstring returns only doc, without signature
            definition.docstring(raw=True),
            preferred_markup_kind,
            signatures=[signature] if signature else None,
        )
    }
