# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/08_completions.ipynb.

# %% auto 0
__all__ = ['relevant_suggestion_keys', 'CompletionsManager']

# %% ../nbs/08_completions.ipynb 4
from .helpers import run_noecho
from .stata_session import StataSession
from .completion_env import CompletionEnv, Env
from fastcore.basics import patch_to
import os
import re
import platform

# %% ../nbs/08_completions.ipynb 5
class CompletionsManager():
    def __init__(self, stata_session: StataSession, available_magics):
        """"""
        self.stata_session = stata_session
        self.available_magics = available_magics
        self.env_helper = CompletionEnv()

# %% ../nbs/08_completions.ipynb 8
@patch_to(CompletionsManager)
def get_globals(self):
    from sfi import Macro
    if self.stata_session.suggestions:
        return {k: Macro.getGlobal(k) for k in self.stata_session.suggestions['globals']}
    else:
        return {}

# %% ../nbs/08_completions.ipynb 9
@patch_to(CompletionsManager)
def get_file_paths(self, chunk):
    """Get file paths based on chunk
    Args:
        chunk (str): chunk of text after last space. Doesn't include string
            punctuation characters
    Returns:
        (List[str]): folders and files at that location
    """
    from sfi import SFIToolkit
    # If local exists, return empty list
    if re.search(r'[`\']', chunk):
        return []

    # Define directory separator
    dir_sep = '/'
    if platform.system() == 'Windows':
        if '/' not in chunk:
            dir_sep = '\\'

    # Get directory without ending file, and without / or \
    if any(x in chunk for x in ['/', '\\']):
        ind = max(chunk.rfind('/'), chunk.rfind('\\'))
        user_folder = chunk[:ind + 1]
        user_starts = chunk[ind + 1:]

        # Replace multiple consecutive / with a single /
        user_folder = re.sub(r'/+', '/', user_folder)
        user_folder = re.sub(r'\\+', r'\\', user_folder)

    else:
        user_folder = ''
        user_starts = chunk

    # Replace globals with their values
    globals_re = r'\$\{?((?![0-9_])\w{1,32})\}?'
    try:
        folder = re.sub(
            globals_re, 
            lambda x: self.get_globals()[x.group(1)], 
            user_folder
        )
    except KeyError:
        # If the global doesn't exist (aka it hasn't been defined in 
        # the Stata environment yet), then there are no paths to check
        return []

    # Use Stata's relative path
    abspath = re.search(r'^([/~]|[a-zA-Z]:)', folder)
    if not abspath:
        folder = SFIToolkit.getWorkingDir() + '/' + folder

    try:
        top_dir, dirs, files = next(os.walk(os.path.expanduser(folder)))
        results = [x + dir_sep for x in dirs] + files
        results = [
            user_folder + x for x in results if not x.startswith('.')
            and re.match(re.escape(user_starts), x, re.I)]

    except StopIteration:
        results = []

    return sorted(results)

# %% ../nbs/08_completions.ipynb 13
relevant_suggestion_keys = {
    Env.NONE: [],
    Env.GENERAL: ['varlist', 'scalars'],
    Env.LOCAL: ['locals'],
    Env.GLOBAL: ['globals'],
    Env.SCALAR: ['scalars'],
    Env.MATRIX: ['matrices'],
    Env.SCALAR_VAR: ['scalars', 'varlist'],
    Env.MATRIX_VAR: ['matrices', 'varlist'],
    Env.STRING: [],
}

@patch_to(CompletionsManager)
def get(self, starts, env, rcomp):
    """Return environment-aware completions list."""
    if env is Env.MAGIC:
        candidate_suggestions = self.available_magics
    else:
        candidate_suggestions = [suggestion
                                 for key in relevant_suggestion_keys[env]
                                 for suggestion in self.stata_session.suggestions[key]]
    relevant_suggestions = [candidate + rcomp 
                            for candidate in candidate_suggestions
                            if candidate.startswith(starts)]
    if env in [Env.GENERAL, Env.STRING]:
        relevant_suggestions += self.get_file_paths(starts)
    return relevant_suggestions

#     elif env == 9:
#         if len(starts) > 1:
#             builtins = [
#                 var for var in mata_builtins if var.startswith(starts)]
#         else:
#             builtins = []

#         if re.search(r'[/\\]', starts):
#             paths = self.get_file_paths(starts)
#         else:
#             paths = []

#         return [
#             var for var in self.stata_session.suggestions['mata']
#             if var.startswith(starts)] + builtins + paths

# %% ../nbs/08_completions.ipynb 14
@patch_to(CompletionsManager)
def do(self, code, cursor_pos, starting_delimiter=None):
    if self.stata_session.suggestions is None:
        self.stata_session.refresh_suggestions()
    env, pos, chunk, rcomp = self.env_helper.get_env(
        code[:cursor_pos], 
        code[cursor_pos:(cursor_pos + 2)],
        starting_delimiter,
    )
    return pos, cursor_pos, self.get(chunk, env, rcomp)
