# 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):
    signature_config = config.settings().get("signature", {})
    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"])
        ),
        "",
    )

    include_docstring = signature_config.get("include_docstring", True)

    # raw docstring returns only doc, without signature
    docstring = definition.docstring(raw=True)
    if not include_docstring:
        if signature:
            docstring = ""
        else:
            docstring = docstring.strip().split("\n")[0].strip()

    return {
        "contents": _utils.format_docstring(
            docstring,
            preferred_markup_kind,
            signatures=[signature] if signature else None,
            signature_config=signature_config,
        )
    }
