#!/usr/bin/env python
"""
CliParser.py, module definition of FoBiS.py CLI Parser object, an istance of argparse.ArgumentParser.
"""
import argparse


def CliParser(appname, description, version):
    cliparser = argparse.ArgumentParser(prog=appname, description=description)
    cliparser.add_argument('-v', '--version', action='version', help='Show version', version='%(prog)s ' + version)
    clisubparsers = cliparser.add_subparsers(title='Commands', description='Valid commands')

    buildparser = clisubparsers.add_parser('build', help='Build all programs found or a specific target')
    buildparser.set_defaults(which='build')
    buildparser_g_compiler = buildparser.add_argument_group('compiler')
    buildparser_g_compiler.add_argument('-compiler', required=False, action='store', default='intel', type=str.lower, choices=('gnu', 'intel', 'g95', 'custom'), help='Compiler used (value is case insensitive, default intel)')
    buildparser_g_compiler.add_argument('-fc', required=False, action='store', default='', help='Specify the Fortran compiler statement, necessary for custom compiler specification (-compiler Custom)')
    buildparser_g_compiler.add_argument('-cflags', required=False, action='store', default='-c', help='Compile flags')
    buildparser_g_compiler.add_argument('-lflags', required=False, action='store', default='', help='Link flags')
    buildparser_g_compiler.add_argument('-p', '--preproc', required=False, action='store', default='', help='Preprocessor flags')
    buildparser_g_compiler.add_argument('-modsw', required=False, action='store', default='', help='Specify the switch for setting the module searching path, necessary for custom compiler specification (-compiler Custom)')
    buildparser_g_compiler.add_argument('-mpi', required=False, action='store_true', default=False, help='Use MPI enabled version of compiler')
    buildparser_g_compiler.add_argument('-mklib', required=False, action='store', default=None, choices=('static', 'shared'), help='Build library instead of program (use with -target switch)')
    buildparser_g_compiler.add_argument('-ch', '--cflags_heritage', required=False, action='store_true', default=False, help='Store cflags as a heritage for the next build: if cflags change re-compile all')
    buildparser_g_dirs = buildparser.add_argument_group('directories')
    buildparser_g_dirs.add_argument('-s', '--src', required=False, action='store', default='./', help='Root-directory of source files [default: ./]')
    buildparser_g_dirs.add_argument('-dbld', '--build_dir', required=False, action='store', default='./', help='Directory containing executable objects [default: ./]')
    buildparser_g_dirs.add_argument('-dobj', '--obj_dir', required=False, action='store', default='./obj/', help='Directory containing compiled objects [default: ./obj/]')
    buildparser_g_dirs.add_argument('-dmod', '--mod_dir', required=False, action='store', default='./mod/', help='Directory containing .mod files of compiled objects [default: ./mod/]')
    buildparser_g_dirs.add_argument('-dlib', '--lib_dir', required=False, action='store', nargs='+', default=[], help='List of directories searched for libraries [default: None]')
    buildparser_g_dirs.add_argument('-i', '--include', required=False, action='store', nargs='+', default=[], help='List of directories for searching included files')
    buildparser_g_files = buildparser.add_argument_group('files')
    buildparser_g_files.add_argument('-t', '--target', required=False, action='store', default=None, help='Specify a target file [default: all programs found]')
    buildparser_g_files.add_argument('-o', '--output', required=False, action='store', default=None, help='Specify the output file name is used with -target switch [default: basename of target]')
    buildparser_g_files.add_argument('-e', '--exclude', required=False, action='store', nargs='+', default=[], help='Exclude a list of files from the building process')
    buildparser_g_files.add_argument('-inc', required=False, action='store', nargs='+', default=[], help='List of custom-defined file extensions for include files')
    buildparser_g_files.add_argument('-libs', required=False, action='store', nargs='+', default=[], help='List of external libraries used that are not into the path: specify with full paths [default: None]')
    buildparser_g_files.add_argument('-vlibs', required=False, action='store', nargs='+', default=[], help='List of external libraries used that are not into the path and that are volatile (can change thus triggering re-building): specify with full paths [default: None]')
    buildparser_g_files.add_argument('-ext_libs', required=False, action='store', nargs='+', default=[], help='List of external libraries used that are into compiler path [default: None]')
    buildparser_g_files.add_argument('-ext_vlibs', required=False, action='store', nargs='+', default=[], help='List of external libraries used that are into compiler path and that are volatile (can change thus triggering re-building) [default: None]')
    buildparser_g_files.add_argument('-dependon', required=False, action='store', nargs='+', default=[], help='List of interdependent external fobos file (and mode) for interdependent building [default: None]')
    buildparser_g_fobos = buildparser.add_argument_group('fobos')
    buildparser_g_fobos.add_argument('-f', '--fobos', required=False, action='store', default=None, help='Specify a "fobos" file named differently from "fobos"')
    buildparser_g_fobos.add_argument('-fci', '--fobos_case_insensitive', required=False, action='store_true', default=False, help='Assume fobos inputs as case insensitive [defaul: False, case sensitive]')
    buildparser_g_fobos.add_argument('-mode', required=False, action='store', default=None, help='Select a mode defined into a fobos file')
    buildparser_g_fobos.add_argument('-lmodes', required=False, action='store_true', default=False, help='List the modes defined into a fobos file')
    buildparser_g_preform = buildparser.add_argument_group('PreForM.py')
    buildparser_g_preform.add_argument('-pfm', '--preform', required=False, action='store_true', default=False, help='Use PreForM.py pre-processor for pre-processing sources file')
    buildparser_g_preform.add_argument('-dpfm', '--pfm_dir', required=False, action='store', default=None, help='Directory containing the sources processed with PreForM.py [default: none, the processed files are removed after used]')
    buildparser_g_preform.add_argument('-epfm', '--pfm_ext', required=False, action='store', nargs='+', default=[], help='List of custom-defined file extensions to be preprocessed by PreForM.py [default: none, all files are preprocessed if PreForM.py is used]')
    buildparser_g_fancy = buildparser.add_argument_group('fancy')
    buildparser_g_fancy.add_argument('-colors', required=False, action='store_true', default=False, help='Activate colors in shell prints [default: no colors]')
    buildparser_g_fancy.add_argument('-l', '--log', required=False, action='store_true', default=False, help='Activate the creation of a log file [default: no log file]')
    buildparser_g_fancy.add_argument('-q', '--quiet', required=False, action='store_true', default=False, help='Less verbose than default')
    buildparser_g_fancy.add_argument('-j', '--jobs', required=False, action='store', default=1, type=int, help='Specify the number of concurrent jobs used for compiling dependencies [default 1]')
    buildparser_g_fancy.add_argument('-m', '--makefile', required=False, action='store', default=None, help='Generate a GNU Makefile for building the project', metavar='MAKEFILE_name')

    cleanparser = clisubparsers.add_parser('clean', help='Clean project: remove all OBJs and MODs files... use carefully')
    cleanparser.set_defaults(which='clean')
    cleanparser_g_compiler = cleanparser.add_argument_group('compiler')
    cleanparser_g_compiler.add_argument('-only_obj', required=False, action='store_true', default=False, help='Clean only compiled objects and not also built targets')
    cleanparser_g_compiler.add_argument('-only_target', required=False, action='store_true', default=False, help='Clean only built targets and not also compiled objects')
    cleanparser_g_compiler.add_argument('-mklib', required=False, action='store', default=None, help='Build library instead of program (use with -target switch); usage: -mklib static or -mklib shared')
    cleanparser_g_compiler.add_argument('-ch', '--cflags_heritage', required=False, action='store_true', default=False, help='Store cflags as a heritage for the next build: if cflags change re-compile all')
    cleanparser_g_dirs = cleanparser.add_argument_group('directories')
    cleanparser_g_dirs.add_argument('-dobj', '--obj_dir', required=False, action='store', default='./obj/', help='Directory containing compiled objects [default: ./obj/]')
    cleanparser_g_dirs.add_argument('-dmod', '--mod_dir', required=False, action='store', default='./mod/', help='Directory containing .mod files of compiled objects [default: ./mod/]')
    cleanparser_g_dirs.add_argument('-dbld', '--build_dir', required=False, action='store', default='./', help='Directory containing executable objects [default: ./]')
    cleanparser_g_files = cleanparser.add_argument_group('files')
    cleanparser_g_files.add_argument('-t', '--target', required=False, action='store', default=None, help='Specify a target file [default: all programs found]')
    cleanparser_g_files.add_argument('-o', '--output', required=False, action='store', default=None, help='Specify the output file name is used with -target switch [default: basename of target]')
    cleanparser_g_fobos = cleanparser.add_argument_group('fobos')
    cleanparser_g_fobos.add_argument('-f', '--fobos', required=False, action='store', default=None, help='Specify a "fobos" file named differently from "fobos"')
    cleanparser_g_fobos.add_argument('-fci', '--fobos_case_insensitive', required=False, action='store_true', default=False, help='Assume fobos inputs as case insensitive [defaul: False, case sensitive]')
    cleanparser_g_fobos.add_argument('-mode', required=False, action='store', default=None, help='Select a mode defined into a fobos file')
    cleanparser_g_fobos.add_argument('-lmodes', required=False, action='store_true', default=False, help='List the modes defined into a fobos file')
    cleanparser_g_fancy = cleanparser.add_argument_group('fancy')
    cleanparser_g_fancy.add_argument('-colors', required=False, action='store_true', default=False, help='Activate colors in shell prints [default: no colors]')

    rulexparser = clisubparsers.add_parser('rule', help='Execute rules defined into a fobos file')
    rulexparser.set_defaults(which='rule')
    rulexparser.add_argument('-f', '--fobos', required=False, action='store', default=None, help='Specify a "fobos" file named differently from "fobos"')
    rulexparser.add_argument('-fci', '--fobos_case_insensitive', required=False, action='store_true', default=False, help='Assume fobos inputs as case insensitive [defaul: False, case sensitive]')
    rulexparser.add_argument('-ex', '--execute', required=False, action='store', default=None, help='Specify a rule (defined into fobos file) to be executed', metavar='RULE')
    rulexparser.add_argument('-ls', '--list', required=False, action='store_true', default=False, help='List the rules defined into a fobos file')
    rulexparser.add_argument('-q', '--quiet', required=False, action='store_true', default=False, help='Less verbose than default')
    rulexparser.add_argument('-colors', required=False, action='store_true', default=False, help='Activate colors in shell prints [default: no colors]')
    return cliparser
