#!/usr/bin/env python3

"""
TODO
- could load shortcuts from environment
"""

import os
from sys import argv, exit
from typing import Tuple, List, Generator, Iterable, Iterator, Sequence, Callable
from itertools import chain

Args = Sequence[str]
StrIter = Iterable[str]

GwCommand = 'gw'
DEBUG = False

actions = (
    'clean', 
    'build', 
    'compileTestKotlin', 
    # todo only if there no -x prefix
    'test', 
    'componentTest', 
    'shadowJar'
)

shortcuts = {
    'c': ['clean'],
    'b': ['build'],
    't': ['test'],
    'bt': ['compileTestKotlin'],
    'ct': ['componentTest'],
    'tct': ['test', 'componentTest'],
    'cb': ['clean', 'build'],
    'cbx': ['clean', 'build', '-x', 'test'],
    'cbt': ['clean', 'build', 'compileTestKotlin', '-x', 'test'],
    'cct': ['cleanComponentTest'],
    'rt': ['cleanTest', 'test'],
    'rct': ['cleanComponentTest', 'componentTest'],
    'nd': ['-x', 'detekt'],
    '-nd': ['-x', 'detekt'],
    'xt': ['-x', 'test'],
    '-nt': ['-x', 'test'],
    'br': ['bootRun'],
    'rb': ['bootRun'],
    'jar': ['shadowJar'],
    '-nc': ['--no-build-cache'],
    '-rr': ['--rerun-tasks'],
    '-rt': ['--rerun-tasks'],
    '-wl': ['--write-locks'],
    '-ef': ['-Penvironment=free'],
    '-el': ['-Penvironment=licensed'],
    '-lic': ['-Penvironment=licensed']
}    

help_text = """\
Support functionality for gw application

Use cases
  gws cbx :tests :tools  
  gws cb ct
  gws cbt
  gws cbx :microservices:afm-exec-api

Options
  --show  doesn't start gw app
  --debug show details about processing
"""


def show_help():
    print(help_text)
    show_shortcuts()
    print()
    exit(1)


def show_shortcuts():
    print('Shortcuts')
    for key, value in shortcuts.items():
        print(f"  {key} ... {' '.join(value)}")


def log(name, obj):
    if DEBUG:
        print(name + str(obj))


def is_module(arg: str):
    return arg.startswith(':')


def flatten(lst):
    return list(chain(*lst))


def replace_shortcut(arg: str) -> List[str]:
    if arg in shortcuts:
        return shortcuts[arg]
    else:
        return [arg]


def split_on_condition(lst: Sequence, condtion):
    good = []
    bad = []
    for item in lst:
        (bad, good)[condtion(item)].append(item)
    return good, bad


def pair_module_with_action(args: Args) -> List[str]:
    modules, rest_args  = split_on_condition(args, is_module)
    log("modules", modules)
    log("args", rest_args)
    if modules:
        _args = []
        for arg in rest_args:
            if arg in actions:
                for module in modules:                
                    _args.append(module + ':' + arg)
            else:
                _args.append(arg)
        return _args
    else:
        return args


def prepare_args(args: Args) -> List[str]:
    args = flatten(map(replace_shortcut, args))
    args = pair_module_with_action(args)
    return args


def prepare_command(args: Args) -> str:
    return GwCommand + ' ' + ' '.join(prepare_args(args))


def try_remove(lst: Sequence, value) -> Tuple[bool, Sequence]:
    filtered = list(filter(lambda x: x != value, lst))
    return len(lst) != len(filtered), filtered


def main(args: List[str]):
    if not args:
        show_help()
    global DEBUG
    DEBUG, args = try_remove(args, '--debug')
    just_show, args = try_remove(args, '--show')
    cmd = prepare_command(args)
    print(cmd)
    if not just_show:
        print()
        os.system(cmd)


if __name__ == '__main__':
    main(argv[1:])
