import argparse
import os

import sltxpkg.util as su
from sltxpkg.command_config import Arg, Commands
from sltxpkg.commands import (cmd_analyze_logfile, cmd_auto_setup, cmd_cleanse,
                              cmd_compile, cmd_dependency, cmd_docker,
                              cmd_gen_gha, cmd_raw_compile, cmd_version)


def valid_file(arg: str) -> str:
    if arg is None or arg.strip() == "":
        raise ValueError("arg vas none or empty")
    if not os.path.isfile(arg):
        raise FileNotFoundError("\"" + arg + "\" must be an existing file")
    return arg


file_help = "the file(s) to load; they will be processed."
file_tx = "file.tex"

sub_parser = Commands({
    'analyze': ((cmd_analyze_logfile, ['log']),
                Arg(description='Analyze a logfile for errors.'),
                [
                    Arg('files', metavar='log.zip',
                        type=str, nargs='*', help=file_help)]
                ),
    'dependency': ((cmd_dependency, ['dep']),
                   Arg(description='Install dependencies on the host system.'),
                   [
        Arg('-l', '--local', metavar='path', dest='local_path', default=None,
            help="This will install the dependency file into the given directory. This might be useful if the compilation should be handled by an online editor. Use '.' to use the current directory."),
        Arg('deps', metavar='dep.yml', type=valid_file, nargs='+',
            help="the file(s) to load the dependencies from.")
    ]),
    'docker': ((cmd_docker, ['do']), Arg(description='Manage the containers to compile with sltx.'), []),
    'compile': ((cmd_compile, ['cmp']), Arg(description="Compile documents with previously installed containers. If docker was disabled this will default to the same behavior as \"raw-compile\" passing on the recipe."),
                [
        Arg('-p', '--profile', dest='profile',
                help="allows to override the configured docker profile. This will enable docker automatically."),
        Arg('-r', '--recipe', dest='recipe',
            help='The recipe to instruct the main compile routine.', required=False, default=None),
        Arg('--root', dest='dock_as_root', action='store_true',
            help='Run the docker container with the lithie-root setup. This may lead to permission errors when you want to delete the caches.', required=False),
        Arg('-l', '--local-texmf', dest='local_texmf', action='store_true', default=False,
            help='include the local texmf tree in the docker container', required=False),
        Arg('--no-local-texmf', dest='local_texmf', action='store_false',
            help='exclude the local texmf tree in the docker container', required=False),
        Arg('-d', '--dependencies', dest='extra_dependencies', action='append', default=[],
            help='additional dependency files to download before the installation. May be supplied multiple times.', required=False),
        Arg('-a', '--args', action='append', metavar='ARGUMENT(S)', dest='extra_arguments', default=[],
            help="Extra arguments. Make sure to prepend them with the appropriate '-' or '--', they will be used as extra_arguments in the recipe."),
        Arg('files', metavar=file_tx, type=str, nargs='*',
            help=file_help)
    ]),
    'raw-compile': ((cmd_raw_compile, ['raw-cmp']), Arg(description="Compile documents using a recipe. This will not start any docker container but will be executed inside one as well."),
                    [
        Arg('-r', '--recipe', dest='recipe',
            help='The recipe to instruct the main compile routine.', required=False, default=None),
        Arg('files', metavar=file_tx, type=str, nargs='*',
            help=file_help),
        Arg('-a', '--args', action='append', metavar='ARGUMENT(S)', dest='extra_arguments', default=[],
            help="Extra arguments. Make sure to prepend them with the appropriate '-' or '--', they will be used as extra_arguments in the recipe."),
        Arg('-d', '--dependency', dest='extra_dependencies', action='append', default=[],
            help='additional dependency files to download before the installation. May be supplied multiple times.', required=False)
    ]),
    'gen-gha': ((cmd_gen_gha, ['gha']), Arg(description='Generate a GitHub workflow To automate compilation.'), []),
    'cleanse': ((cmd_cleanse, ['cls']), Arg(description="This will clean all additional sltx-files in the current directory (like \"sltx-log-*\" files). It may clean more, if you pass the corresponding flags. Please note, that cleanse will only read the current config. If you've changed some configurations they will be used."),
                [
        Arg('-C', '--cache', dest='cleanse_cache', action='store_true',
                help="If set, sltx will clean the cache."),
        Arg('--all', dest='cleanse_all', action='store_true',
            help="If set, sltx will clean the texmf-tree (sltx) and the cache as-well."),
        Arg('-e', '--exclude', action='append', metavar='pattern', dest='exclude_patterns',
            help="Exclude all files/directories matching this pattern. May be supplied multiple times.")
    ]),
    'auto-setup': ((cmd_auto_setup, []), Arg(description='Setup a basic version of sltx (this requires docker to be setup).'),
                   [
        Arg('-d', '--dependencies', dest='auto_deps', action='store_true',
            help='This will install the recommended dependencies on your host system. This is helpful if you have texlive installed and want your editor to recognize the libraries as well.')
    ]),
    'version': ((cmd_version, []), Arg(description='Show the version-info for sltx.'), [])
})

parser = argparse.ArgumentParser(
    description="sltx, a Simple LaTeX utility", epilog="sltx Version: " + su.get_version())

# commands, parser.add_mutually_exclusive_group()
parser.add_argument('-c', '--config', dest='config', metavar='config.yml',
                    required=False, type=valid_file,
                    help="the file to load the configuration from.")

parser.add_argument('-t', '--threads', metavar='N', dest='threads', type=int,
                    help="number of threads to run the installation. Default is 1. This number will only affect some routines.",
                    default=-1)

parser.add_argument('-q', '--quiet', dest='quiet',
                    required=False, action='store_true',
                    help="Set the flag if output is to be reduced")

parser.add_argument('-v', '--verbose', dest='verbose',
                    required=False, action='store_true',
                    help="Output in verbose mode -> more information from sltx")

parser.add_argument('--log', dest='log',
                    required=False, action='store_true',
                    help="Write to logfile. This is experimental.")

# TODO: Format support with mlatexformat?

cmd_parser = parser.add_subparsers(
    title='command', description="Select the command for sltx", metavar=set(sub_parser.cmds.keys()),
    help="Help for the specific command. You may use shortcuts for them: " +
    str([k[1] for k in sub_parser.helper_values() if len(k[1]) != 0]),
    dest='command')

sub_parser.generate(cmd_parser)
