import click
import os

from popper import log as logging
from popper.cli import log, pass_context
from popper.parser import Workflow
from popper.runner import WorkflowRunner


@click.command(
    'run', short_help='Run a workflow or step.')
@click.argument(
    'step',
    required=False
)
@click.option(
    '-f',
    '--wfile',
    help='File containing the definition of the workflow.',
    required=True
)
@click.option(
    '--debug',
    help=(
        'Generate detailed messages of what popper does (overrides --quiet)'),
    required=False,
    is_flag=True
)
@click.option(
    '--dry-run',
    help='Do not run the workflow, only print what would be executed.',
    required=False,
    is_flag=True
)
@click.option(
    '--log-file',
    help='Path to a log file. No log is created if this is not given.',
    required=False
)
@click.option(
    '--quiet',
    help='Do not print output generated by steps.',
    required=False,
    is_flag=True
)
@click.option(
    '--reuse',
    help='Reuse containers between executions (persist container state).',
    required=False,
    is_flag=True,
)
@click.option(
    '--engine',
    help='Specify runtime for executing the workflow [default: docker].',
    type=click.Choice(['docker', 'singularity', 'vagrant']),
    required=False,
    default='docker'
)
@click.option(
    '--skip',
    help=('Skip the given step (can be given multiple times).'),
    required=False,
    default=list(),
    hidden=True,
    multiple=True
)
@click.option(
    '--skip-clone',
    help='Skip cloning repositories (assume they have been cloned).',
    required=False,
    is_flag=True
)
@click.option(
    '--skip-pull',
    help='Skip pulling container images (assume they exist in local cache).',
    required=False,
    is_flag=True
)
@click.option(
    '--substitution',
    help=('A key-value pair defining a substitution. '
          'Can be given multiple times.'),
    required=False,
    default=list(),
    multiple=True
)
@click.option(
    '--allow-loose',
    help='Do not throw an error if a substitution variable passed as an '
    'argument is unused in the workflow definition.',
    required=False,
    is_flag=True
)
@click.option(
    '--with-dependencies',
    help='When STEP is given, execute all its dependencies as well.',
    required=False,
    hidden=True,
    is_flag=True
)
@click.option(
    '-w',
    '--workspace',
    help='Path to workspace folder.',
    required=False,
    show_default=False,
    default=os.getcwd()
)
@click.option(
    '-c', '--conf', help='Runtime configuration options.', required=False
)
@pass_context
def cli(ctx, step, wfile, debug, dry_run, log_file, quiet, reuse,
        engine, skip, skip_pull, skip_clone, substitution, allow_loose,
        with_dependencies, workspace, conf):
    """Runs a Popper workflow. Only execute STEP if given."""
    # set the logging levels.
    level = 'STEP_INFO'
    if quiet:
        level = 'INFO'
    if debug:
        level = 'DEBUG'
    log.setLevel(level)

    if dry_run:
        logging.msg_prefix = "DRYRUN: "

    if log_file:
        # also log to a file
        logging.add_log(log, log_file)

    # check conflicting flags and fail if needed
    if with_dependencies and not step:
        log.fail('`--with-dependencies` can only be used when '
                 'STEP argument is given.')
    if skip and step:
        log.fail('`--skip` can not be used when STEP argument is passed.')

    # invoke wf factory; handles formats, validations, filtering
    wf = Workflow.new(wfile, step=step, skipped_steps=skip,
                      substitutions=substitution, allow_loose=allow_loose,
                      include_step_dependencies=with_dependencies)

    # instantiate the runner
    runner = WorkflowRunner(config_file=conf, dry_run=dry_run, reuse=reuse,
                            skip_pull=skip_pull, skip_clone=skip_clone,
                            workspace_dir=workspace)
    runner.run(wf)
