# -*- coding: utf-8 -*-
# -- This file is part of the Apio project
# -- (C) 2016-2019 FPGAwars
# -- Author Jesús Arroyo
# -- Licence GPLv2

import click

from os import listdir
from os.path import isfile
from sys import exit as sys_exit

from apio import util

# -- The commands are python modules located in the commands folder
# -- Get the absolute path to all the commands
commands_folder = util.get_folder('commands')

# -- Auxiliary function used sfor reformating the Help string output
def find_commands_help(help, commands):
    """ Extract the commands from the help string
        Return a list with the command + description
    """
    commands_help = []
    for line in list(help):
        for command in commands:
            if (' ' + command) in line:
                if line in help:
                    help.remove(line)
                    commands_help.append(line)
    return commands_help


# -- Main Click Class
# -- It is extended for including methods for for getting and listing the commands
class ApioCLI(click.MultiCommand):

    #-- Return  a list of all the available commands
    def list_commands(self, ctx):
        rv = []

        #-- The supported command are python files located in the commands folder
        #-- Except __init__.pys
        for filename in listdir(commands_folder):
            if filename.startswith('__init__'):
                continue
            if filename.endswith('.py'):
                rv.append(filename[:-3])

        rv.sort()
        return rv

    # -- Return the code function (cli) of the command name. This cli function is called  
    # -- whenever the name command is issued
    def get_command(self, ctx, name):
        ns = {}

        # -- Get the full filename of the python file for the command name
        fn = util.safe_join(commands_folder, name + '.py')
        
        # -- Return the cli function of the command
        if isfile(fn):
            with open(fn) as f:
                code = compile(f.read(), fn, 'exec')
                eval(code, ns, ns)
            return ns.get('cli')


# -- This function is the ENTRY POINT. Whenever a command is issued,
# -- this function is called
@click.command(cls=ApioCLI, invoke_without_command=True)
@click.pass_context
@click.version_option()
def cli(ctx):

    # -- No command typed: show help
    if ctx.invoked_subcommand is None:

        # -- The help string is automatically generated by Click  
        # -- It could be directly printed on the console but...
        help = ctx.get_help()

        # -- Let's change the format so that the commands are divided
        # -- into three categories: Project, Setup and Utilitys
        help = help.split('\n')

        # -- Setup commands
        setup_help = find_commands_help(help, ['drivers', 'init',
                                               'install', 'uninstall'])

        # -- Utility commands
        util_help = find_commands_help(help, ['boards', 'config', 'examples',
                                              'raw', 'system', 'upgrade'])

        # -- Reformat the Help string
        help = '\n'.join(help)
        help = help.replace('Commands:\n', 'Project commands:\n')
        help += "\n\nSetup commands:\n"
        help += '\n'.join(setup_help)
        help += "\n\nUtility commands:\n"
        help += '\n'.join(util_help)
        help += '\n'

        click.secho(help)

    # -- If there is a command, it is executed when this function is finished
    # -- Debug: print the command invoked
    # print(f"{ctx.invoked_subcommand}")


if __name__ == '__main__':  # pragma: no cover
    sys_exit()
