#   Copyright 2010-2025 Antonio Cuni
#                       Daniel Hahler
#
#                        All Rights Reserved
"""Colorful tab completion for Python prompt"""
from __future__ import annotations

from _colorize import ANSIColors, get_colors, get_theme
import rlcompleter
import keyword
import types

TYPE_CHECKING = False

if TYPE_CHECKING:
    from typing import Any
    from _colorize import Theme


def safe_getattr(obj, name):
    # Mirror rlcompleter's safeguards so completion does not
    # call properties or reify lazy module attributes.
    if isinstance(getattr(type(obj), name, None), property):
        return None
    if (isinstance(obj, types.ModuleType)
        and isinstance(obj.__dict__.get(name), types.LazyImportType)
    ):
        return obj.__dict__.get(name)
    return getattr(obj, name, None)


def colorize_matches(names: list[str], values: list[Any], theme: Theme) -> list[str]:
    return [
        _color_for_obj(name, obj, theme)
        for name, obj in zip(names, values)
    ]

def _color_for_obj(name: str, value: Any, theme: Theme) -> str:
    t = type(value)
    color = _color_by_type(t, theme)
    return f"{color}{name}{ANSIColors.RESET}"


def _color_by_type(t, theme):
    typename = t.__name__
    # this is needed e.g. to turn method-wrapper into method_wrapper,
    # because if we want _colorize.FancyCompleter to be "dataclassable"
    # our keys need to be valid identifiers.
    typename = typename.replace('-', '_').replace('.', '_')
    return getattr(theme.fancycompleter, typename, ANSIColors.RESET)


class Completer(rlcompleter.Completer):
    """
    When doing something like a.b.<tab>, keep the full a.b.attr completion
    stem so readline-style completion can keep refining the menu as you type.

    Optionally, display the various completions in different colors
    depending on the type.
    """
    def __init__(
        self,
        namespace=None,
        *,
        use_colors='auto',
        consider_getitems=True,
    ):
        from _pyrepl import readline
        rlcompleter.Completer.__init__(self, namespace)
        if use_colors == 'auto':
            # use colors only if we can
            use_colors = get_colors().RED != ""
        self.use_colors = use_colors
        self.consider_getitems = consider_getitems

        if self.use_colors:
            # In GNU readline, this prevents escaping of ANSI control
            # characters in completion results. pyrepl's parse_and_bind()
            # is a no-op, but pyrepl handles ANSI sequences natively
            # via real_len()/stripcolor().
            readline.parse_and_bind('set dont-escape-ctrl-chars on')
            self.theme = get_theme()
        else:
            self.theme = None

        if self.consider_getitems:
            delims = readline.get_completer_delims()
            delims = delims.replace('[', '')
            delims = delims.replace(']', '')
            readline.set_completer_delims(delims)

    def complete(self, text, state):
        # if you press <tab> at the beginning of a line, insert an actual
        # \t. Else, trigger completion.
        if text == "":
            return ('\t', None)[state]
        else:
            return rlcompleter.Completer.complete(self, text, state)

    def _callable_postfix(self, val, word):
        # disable automatic insertion of '(' for global callables
        return word

    def _callable_attr_postfix(self, val, word):
        return rlcompleter.Completer._callable_postfix(self, val, word)

    def global_matches(self, text):
        names = rlcompleter.Completer.global_matches(self, text)
        prefix = commonprefix(names)
        if prefix and prefix != text:
            return [prefix]

        names.sort()
        values = []
        for name in names:
            clean_name = name.rstrip(': ')
            if keyword.iskeyword(clean_name) or keyword.issoftkeyword(clean_name):
                values.append(None)
            else:
                try:
                    values.append(eval(name, self.namespace))
                except Exception:
                    values.append(None)
        if self.use_colors and names:
            return self.colorize_matches(names, values)
        return names

    def attr_matches(self, text):
        try:
            expr, attr, names, values = self._attr_matches(text)
        except ValueError:
            return []

        if not names:
            return []

        if len(names) == 1:
            # No coloring: when returning a single completion, readline
            # inserts it directly into the prompt, so ANSI codes would
            # appear as literal characters.
            return [self._callable_attr_postfix(values[0], f'{expr}.{names[0]}')]

        prefix = commonprefix(names)
        if prefix and prefix != attr:
            return [f'{expr}.{prefix}']  # autocomplete prefix

        names = [f'{expr}.{name}' for name in names]
        if self.use_colors:
            return self.colorize_matches(names, values)
        return names

    def _attr_matches(self, text):
        expr, attr = text.rsplit('.', 1)
        if '(' in expr or ')' in expr:  # don't call functions
            return expr, attr, [], []
        try:
            thisobject = eval(expr, self.namespace)
        except Exception:
            return expr, attr, [], []

        # get the content of the object, except __builtins__
        words = set(dir(thisobject)) - {'__builtins__'}

        if hasattr(thisobject, '__class__'):
            words.add('__class__')
            words.update(rlcompleter.get_class_members(thisobject.__class__))
        names = []
        values = []
        n = len(attr)
        if attr == '':
            noprefix = '_'
        elif attr == '_':
            noprefix = '__'
        else:
            noprefix = None

        # sort the words now to make sure to return completions in
        # alphabetical order. It's easier to do it now, else we would need to
        # sort 'names' later but make sure that 'values' in kept in sync,
        # which is annoying.
        words = sorted(words)
        while True:
            for word in words:
                if (
                    word[:n] == attr
                    and not (noprefix and word[:n+1] == noprefix)
                ):
                    value = safe_getattr(thisobject, word)
                    names.append(word)
                    values.append(value)
            if names or not noprefix:
                break
            if noprefix == '_':
                noprefix = '__'
            else:
                noprefix = None

        return expr, attr, names, values

    def colorize_matches(self, names, values):
        return colorize_matches(names, values, self.theme)


def commonprefix(names):
    """Return the common prefix of all 'names'"""
    if not names:
        return ''
    s1 = min(names)
    s2 = max(names)
    for i, c in enumerate(s1):
        if c != s2[i]:
            return s1[:i]
    return s1
