#!/usr/bin/env python3
# PYTHON_ARGCOMPLETE_OK
# encoding=utf8

import sys
import subprocess
import argcomplete
import argparse

# Test if Redis was launched and start it
import redis
rs = redis.Redis("localhost")
try:
    response = rs.client_list()
except redis.ConnectionError:
    subprocess.Popen(
        '/usr/bin/redis-server &',
        stdout=subprocess.PIPE, stderr=subprocess.PIPE,
        shell=True
    )

from linkmanager.translation import gettext as _
from linkmanager import interface, __version__, __appname__
TTYInterface = interface()


def version(args, verbose=False):
    print('%s %s (python %s)' % (
        __appname__, __version__, sys.version
    ))


def webserver(args, verbose=False):
    browser = None
    if len(args) > 0:
        browser = args[0]
    from linkmserver import run
    run(browser)

choices = {
    'add': ['a', 'add', _('add links'), TTYInterface.addlinks],
    'version': ['v', 'version', _('show linkmanager version'), version],
    'udpate': ['u', 'update', _('update links'), TTYInterface.updatelinks],
    'remove': ['r', 'remove', _('remove links'), TTYInterface.removelinks],
    'flush': [
        'f', 'flush',
        _('flush the entire database'), TTYInterface.flush
    ],
    'load': ['l', 'load', _('load a json database file'), TTYInterface.load],
    'dump': [
        'd', 'dump',
        _('dump all database to a json file'), TTYInterface.dump
    ],
    'search': [
        's', 'search',
        _('search links on database'), TTYInterface.searchlinks
    ],
    'web': ['w', 'web', _('launch a webservice'), webserver],
}


class Choices(object):
    """ LinkManager choices """
    short_cmd = [v[0] for v in choices.values()]
    long_cmd = [v[1] for v in choices.values()]

    @classmethod
    def cmd(cls):
        """ Return a list of LinkManager choices """
        return cls.short_cmd + cls.long_cmd

    @classmethod
    def call(cls, choice):
        """ Call the good sub-command """
        for c in choices.values():
            if c[0] == choice or c[1] == choice:
                return c[3]

    @staticmethod
    def descriptions():
        """ Help give short and long command and her description """
        description = [
            '\n'
            + _('Choices supports the following: (short cmd/cmd)')
            + '\n'
        ]
        max_size = max([max(len(v[0]), len(v[1])) for v in choices.values()])
        for c in choices:
            spaces = ' ' * (
                4 + max_size - len(choices[c][0]) - len(choices[c][1])
            )
            description.append(
                '    {cmd} / {long_cmd}{spaces}  - {help}\n'.format(
                    cmd=choices[c][0], long_cmd=choices[c][1],
                    spaces=spaces, help=choices[c][2]
                )
            )
        return ''.join(description)


def choice_completer(prefix, parsed_args, **kwargs):
    if vars(parsed_args)['choice'] == 's':
        # tag completer
        return TTYInterface.suggest(prefix)

if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        formatter_class=argparse.RawTextHelpFormatter,
        epilog=Choices.descriptions(),
        description=_('Manage your Links ...')
    )
    parser.add_argument(
        'choice',
        choices=Choices.cmd()
    )
    parser.add_argument(
        '-f', '--forced',
        help=_('force command to be quiet and without input'),
        default=False, action='store_const', const='forced'
    )
    parser.add_argument(
        '-v', '--verbose', help=_('verbose option'),
        default=False, action='store_const', const='verbose'
    )
    parser.add_argument(
        'value', nargs='*'
    ).completer = choice_completer

    argcomplete.autocomplete(parser)
    args = parser.parse_args()
    args = vars(args)

    try:
        f_name = Choices.call(args['choice']).__name__
        if f_name == 'flush':
            Choices.call(args['choice'])(args['value'] + [args['forced']])
        elif f_name == 'dump':
            Choices.call(args['choice'])()
        else:
            verbose = False
            if args['verbose'] == 'verbose':
                verbose = True
            Choices.call(args['choice'])(args['value'], verbose)
    except KeyboardInterrupt:
        print('\n' + _('Ctrl + C interruption'))
