#!/usr/bin/env python3
"""
Retrieve the gravity esorex list of recipes, associated options
and documentation
@author: J. Brulé
"""
import subprocess
import numpy as np
import argparse
import re
import shutil


def check_esorex_path():
    """
    check if esorex command is in the PATH
    """
    if not shutil.which("esorex"):
        print("check your esorex environment")
        exit()


def retrieve_esorex_man(recipe, recipe_dir=None):
    """
    retrieve the man page TODO:or check the cache
    """
    check_esorex_path()
    # Build the system call
    syscall = "esorex -man"
    if (recipe_dir is not None):
        syscall = syscall + " -recipe-dir="+args.recipe_dir

    # Call esorex
    raw_help = subprocess.check_output(syscall+"  "+recipe, shell=True,
                                       universal_newlines=True)
    return raw_help


def retrieve_esorex_recipes():
    """
    retrieve the list of known esorex recipes TODO:or check the cache
    """
    check_esorex_path()
    # Build the system call
    syscall = "esorex --recipes"

    # Call esorex
    list_recipes = subprocess.check_output(syscall, shell=True,
                                           universal_newlines=True)
    return list_recipes


def create_esorex_help(help_mesg):
    """
    print the esorex man page
    """
    keyword = ["NAME", "SYNOPSIS", "DESCRIPTION", "OPTIONS",
               "AUTHOR", "BUGS", "RELEASE", "LICENSE"]
    tab = re.split('\n', help_mesg)
    for i in keyword:
        index_name = tab.index(i)
        print(i)
        match i:
            case "NAME" | "SYNOPSIS" | "AUTHOR" | "BUGS" | "RELEASE":
                print(tab[index_name+1])
            case "DESCRIPTION":
                tab_desc = tab[index_name+1:
                               tab.index(keyword[keyword.index(i)+1])]
                parse_desc(tab_desc)

            case "OPTIONS":
                tab_opts = tab[index_name+1:
                               tab.index(keyword[keyword.index(i)+1])]
                opts = parse_options(tab_opts)
                for key, value in opts.items():
                    print(key, " : " + value)

            case "LICENSE":
                print("".join(tab[index_name+1:]))
            case _:
                print("ERRRRR")


def retrieve_recipe_options(recipe, recipe_dir=None):
    """
    retrieve the recipes options
    """
    keyword = ["NAME", "SYNOPSIS", "DESCRIPTION", "OPTIONS",
               "AUTHOR", "BUGS", "RELEASE", "LICENSE"]
    man = retrieve_esorex_man(recipe, recipe_dir)
    tab = re.split('\n', man)
    index_name = tab.index("OPTIONS")
    tab_opts = tab[index_name+1:
                   tab.index(keyword[keyword.index("OPTIONS")+1])]
    opts = parse_options(tab_opts)
    for key, value in opts.items():
        print(recipe+"." + key.replace("--", ""), ": " + value + '\n')


# check to modify
def implement_recipe_options(parser, options=[]):
    """
    pass the recipes options to the parser and return a dict of them
    """
    d_opt = dict()
    dpass = "false"
    for ido, o in enumerate(options):
        if dpass == "true":
            dpass = "false"
            continue
        if '=' in o:
            recipe = o.split('=')[0].split('.')[0].replace('esorex', '')
            opt = o.split('=')[0].split('.')[1]
            value = o.split('=')[1]
            d_opt = d_opt | {recipe+"."+opt: value}
            parser.add_argument('--'+opt, dest=recipe, default=value,
                                help='(see esorex -h '+recipe+')', metavar='')
        else:
            recipe = o.split('.')[0].replace('esorex', '')
            opt = o.split('.')[1]

            value = options[ido+1]
            d_opt = d_opt | {recipe+"."+opt: value}
            parser.add_argument('--'+opt, dest=recipe, default=value,
                                help='(see esorex -h '+recipe+')', metavar='')
            dpass = "true"
    return d_opt


def parse_man_by_keyword2(help_mesg, keyword):

    ref_keyword = ["NAME", "SYNOPSIS", "DESCRIPTION", "OPTIONS",
                   "AUTHOR", "BUGS", "RELEASE", "LICENSE"]
    tab = re.split('\n', help_mesg)
    index_name = tab.index(keyword)
    print(keyword)
    match keyword:
        case "NAME" | "SYNOPSIS" | "AUTHOR" | "BUGS" | "RELEASE":
            print(tab[index_name+1])
        case "DESCRIPTION":
            tab_desc = tab[index_name+1:
                           tab.index(ref_keyword[ref_keyword.index(keyword)+1])
                           ]
            parse_desc(tab_desc)

        case "OPTIONS":
            tab_opts = tab[index_name+1:
                           tab.index(ref_keyword[ref_keyword.index(keyword)+1])
                           ]
            parse_options(tab_opts)

        case "LICENSE":
            print(tab[index_name+1:])
        case _:
            print("ERROR")


def parse_man_by_keyword(help_mesg, keyword):
    """
    parse the esorex man page by keyword
    """
    ref_keyword = ["NAME", "SYNOPSIS", "DESCRIPTION", "OPTIONS",
                   "AUTHOR", "BUGS", "RELEASE", "LICENSE"]
    tab = re.split('\n', help_mesg)
    for i in keyword:
        index_name = tab.index(i)
        print(i)
        match i:
            case "NAME" | "SYNOPSIS" | "AUTHOR" | "BUGS" | "RELEASE":
                print(tab[index_name+1])
            case "DESCRIPTION":
                tab_desc = tab[index_name+1:
                               tab.index(ref_keyword[ref_keyword.index(i)+1])]
                parse_desc(tab_desc)

            case "OPTIONS":
                tab_opts = tab[index_name+1:
                               tab.index(ref_keyword[ref_keyword.index(i)+1])]
                opts = parse_options(tab_opts)
                for key, value in opts.items():
                    print(key, " : " + value)

            case "LICENSE":
                print(tab[index_name+1:])
            case _:
                print("ERRRRR")


def parse_man_by_index(help_mesg, index):
    """
    parse the esorex man page by index
    """
    keyword = ["NAME", "SYNOPSIS", "DESCRIPTION", "OPTIONS",
               "AUTHOR", "BUGS", "RELEASE", "LICENSE"]
    tab = re.split('\n', help_mesg)
    my_array = np.array(tab)
    indexes = np.where(np.isin(tab, keyword))[0].tolist()
    for i in indexes:
        if indexes.index(i) < len(indexes)-1:
            print(my_array[i:indexes[indexes.index(i)+1]])
        else:
            print(my_array[i:])


def find_block(lines, start, end):
    s = np.where(np.array([start in line for line in lines]))[0][0] + 1
    e = np.where(np.array([end in line for line in lines]))[0][0]
    return [out for out in lines[s:e] if out != '']


def parse_options(opts):
    """
    parse the options section of the esorex man page
    """
    options = {}
    previous_key = ''
    # -5 to remove the esorex-3.13.7/src/er_help.c notice
    # Note that it is also possible to create a configuration file containing
    # these options, along with suitable default values. Please refer to the
    # details provided by the 'esorex --help' command.
    for i in opts[:-5]:
        if i.strip()[:2] == '--':
            tab = re.split(':', "".join(i))
            previous_key = tab[0].strip()
            options[tab[0].strip()] = tab[1].strip()
        else:
            if previous_key in options:
                options[previous_key] = options[previous_key] + i.strip()
    return options


def parse_desc(desc):
    """
    parse the description section of the esorex man page
    """
    for i in desc:
        print(i)


usage = """
description:
    Retrieve the gravity esorex list of recipes, associated options
    and documentation
    """

examples = """
Usage:
    recipes-esorex-help.py -l
    recipes-esorex-help.py -m
    recipes-esorex-help.py -t recipe
    recipes-esorex-help.py -lo recipe
    """

#
# Implement options
#

formatter = argparse.RawDescriptionHelpFormatter
parser = argparse.ArgumentParser(description=usage, epilog=examples,
                                 formatter_class=formatter)

# not tested
parser.add_argument("--recipe-dir", dest="recipe_dir",
                    default=None, help="Option for esorex")

parser.add_argument("--list_recipes", "-l", dest='list',
                    help="List recipes", action="store_true")

parser.add_argument("--test", "-t", dest='test', nargs=1, metavar=('RECIPE'),
                    help="Tests functions")

parser.add_argument("--man", "-m", dest='man', nargs=1, metavar=('RECIPE'),
                    help="Show recipe manual")
parser.add_argument("--list-options", "-lo", dest="listoptions", nargs=1,
                    metavar=('RECIPE'), help="Show recipe options")
#
# Main program
#

if __name__ == "__main__":

    args = parser.parse_args()

    if not any(vars(args).values()):
        # display help message when no args are passed.
        parser.print_help()
        exit()

    if args.list:
        # print("going to list recipes")
        # Build the system call
        syscall = "esorex --recipes"
        if (args.recipe_dir is not None):
            syscall = syscall + " -recipe-dir="+args.recipe_dir

        # Call esorex
        check_esorex_path()
        raw_help = subprocess.check_output(syscall,
                                           shell=True,
                                           universal_newlines=True)
        print(raw_help)
        exit()

    if args.man:
        if len(args.man) == 0:
            parser.error("the following arguments are required: recipe")
            parser.print_help()
        recipe = args.man[0]
        raw_help = retrieve_esorex_man(recipe, args.recipe_dir)
        print(raw_help)

    if args.listoptions:
        print('\n')
        if len(args.listoptions) == 0:
            parser.error("the following arguments are required: recipe")
            parser.print_help()
            exit()
        else:
            recipe = args.listoptions[0]
            retrieve_recipe_options(recipe)

    if args.test:
        if len(args.test) == 0:
            parser.error("the following arguments are required: recipe")
            parser.print_help()
        recipe = args.test[0]
        print(('Build help for recipe '+recipe+':'))

        raw_help = retrieve_esorex_man(recipe, args.recipe_dir)
        print("\n")
        print("=======>simple printing")
        print(raw_help)
        print("\n")
        print("=======>version retrieve and parse esorex help")
        create_esorex_help(raw_help)
        print("\n")
        print("=======>version parsing by keyword OPTIONS")
        keyword = ["OPTIONS"]
        parse_man_by_keyword(raw_help, keyword)
        print("\n")
        print("=======>version parsing by keyword DESCRIPTION")
        keyword = ["DESCRIPTION"]
        parse_man_by_keyword(raw_help, keyword)
        print("\n")

        print(f"=======>retrieve recipe option {recipe}")
        retrieve_recipe_options(recipe, args.recipe_dir)
        exit()
