from pathlib import Path

from IPython.terminal.shortcuts import create_ipython_shortcuts

def name(c):
    s = c.__class__.__name__
    if s == '_Invert':
        return '(Not: %s)' % name(c.filter)
    if s in log_filters.keys():
        return '(%s: %s)' % (log_filters[s], ', '.join(name(x) for x in c.filters))
    return log_filters[s] if s in log_filters.keys() else s


def sentencize(s):
    """Extract first sentence
    """
    s = s.replace('\n', ' ').strip().split('.')
    s = s[0] if len(s) else s
    try:
        return " ".join(s.split())
    except AttributeError:
        return s


def most_common(lst, n=3):
    """Most common elements occurring more then `n` times
    """
    from collections import Counter

    c = Counter(lst)
    return [k for (k, v) in c.items() if k and v > n]


def multi_filter_str(flt):
    """Yield readable conditional filter
    """
    assert hasattr(flt, 'filters'), 'Conditional filter required'
    yield name(flt)


log_filters = {'_AndList': 'And', '_OrList': 'Or'}
log_invert =  {'_Invert'}

class _DummyTerminal:
    """Used as a buffer to get prompt_toolkit bindings
    """
    handle_return = None
    input_transformer_manager = None
    display_completions = None
    editing_mode = "emacs"


ipy_bindings = create_ipython_shortcuts(_DummyTerminal()).bindings

dummy_docs = []  # ignore bindings without proper documentation

common_docs = most_common([kb.handler.__doc__ for kb in ipy_bindings])
if common_docs:
    dummy_docs.extend(common_docs)

dummy_docs = list(set(dummy_docs))

single_filter = {}
multi_filter =  {}
for kb in ipy_bindings:
    doc = kb.handler.__doc__
    if not doc or doc in dummy_docs:
        continue

    shortcut = ' '.join([k if isinstance(k, str) else k.name for k in kb.keys])
    shortcut += shortcut.endswith('\\') and '\\' or ''
    if hasattr(kb.filter, 'filters'):
        flt = ' '.join(multi_filter_str(kb.filter))
        multi_filter[(shortcut, flt)] = sentencize(doc)
    else:
        single_filter[(shortcut, name(kb.filter))] = sentencize(doc)


if __name__ == '__main__':
    here = Path(__file__).parent
    dest = here / "source" / "config" / "shortcuts"

    def sort_key(item):
        k, v = item
        shortcut, flt = k
        return (str(shortcut), str(flt))

    for filters, output_filename in [
        (single_filter, "single_filtered"),
        (multi_filter, "multi_filtered"),
    ]:
        with (dest / "{}.csv".format(output_filename)).open(
            "w", encoding="utf-8"
        ) as csv:
            for (shortcut, flt), v in sorted(filters.items(), key=sort_key):
                csv.write(":kbd:`{}`\t{}\t{}\n".format(shortcut, flt, v))
