#!/usr/bin/env python
"""
Runs the QIN pipeline.
"""

import sys
import os
import imp
import argparse
from qiutil import command

NIPYPE_LOG_DIR_ENV_VAR = 'NIPYPE_LOG_DIR'
"""The environment variable used by Nipype to set the log directory."""

def main(argv=sys.argv):
    # Parse the command line arguments.
    inputs, opts = _parse_arguments()

    # Break out the logging options.
    log_opts = {k: opts.pop(k) for k in ['log', 'log_level'] if k in opts}
    # Configure the logger.
    command.configure_log('qipipe', log_opts)
    # Set the Nipype log directory environment variable before importing
    # any nipype module. The code below works around the following Nipype
    # bug:
    # * Nipype requires a log directory. If the Nipype log directory is
    #   set to /dev/null, then Nipype raises an error. The work-around
    #   is to set the NIPYPE_LOG_DIR environment variable to a new temp
    #   directory.
    if 'log' in log_opts:
        log_file = os.path.abspath(log_opts.get('log'))
        if log_file == '/dev/null':
            # Work around the Nipype bug described above.
            log_dir = tempfile.mkdtemp(prefix='qi_')
        else:
            log_dir = os.path.dirname(log_file)
        if not os.path.exists(log_dir):
            os.makedirs(log_dir)
        os.environ[NIPYPE_LOG_DIR_ENV_VAR] = log_dir

    # Import the qipipe pipeline module after configuring the logger
    # above.
    from qipipe.pipeline import qipipeline as qip

    # Run the QIN workflow.
    qip.run(*inputs, **opts)

    return 0


def _parse_arguments():
    """
    Parses the command line arguments.

    :return: the (inputs, options) tuple, where inputs is the non-option
        arguments and options is an {option: value} dictionary
    """
    parser = argparse.ArgumentParser()
    
    # The log options.
    command.add_log_options(parser)

    # The actions.
    parser.add_argument('--stage', dest='actions', action='append_const',
                        const='stage', help='stage the input DICOM files')
    parser.add_argument('--register', dest='actions', action='append_const',
                        const='register', help='register the scans')
    parser.add_argument('--model', dest='actions', action='append_const',
                        const='model', help='model the realigned images')
    parser.add_argument('--dry-run', action='store_true',
                        help='prepare but do not run the pipeline')
    
    # The resume option.
    parser.add_argument('--resume', action='store_true',
                        help='resume staging on existing sessions (default false)')
    
    # The AIRC collection to stage.
    coll_grp = parser.add_mutually_exclusive_group()
    coll_grp.add_argument('-b', '--breast', help='the breast TCIA collection',
                          dest='collection', action='store_const',
                          const='Breast')
    coll_grp.add_argument('-s', '--sarcoma',
                          help='the sarcoma TCIA collection',
                          dest='collection', action='store_const',
                          const='Sarcoma')

    # The output and work options.
    parser.add_argument('-o', '--output',
                        help='the destination directory'
                             ' (default current directory)',
                        metavar='DIR', dest='dest')
    parser.add_argument('-w', '--work',
                        help='the work directory'
                             ' (default a new temp directory)',
                        metavar='DIR', dest='base_dir')

    # The registration arguments.
    parser.add_argument('--registration',
                        help='the XNAT registration resource name',
                        metavar='RESOURCE')
    technique_grp = parser.add_mutually_exclusive_group()
    technique_grp.add_argument('--ants',
                               help="ANTS registration (the default)",
                               dest='technique', action='store_const',
                               const='ants')
    technique_grp.add_argument('--fnirt', help="FNIRT registration",
                               dest='technique', action='store_const',
                               const='fnirt')
    technique_grp.add_argument('--mock', help="Mock registration",
                               dest='technique', action='store_const',
                               const='mock')

    # The modeling arguments.
    parser.add_argument('--modeling',
                        help='the XNAT modeling resource name',
                        metavar='RESOURCE')

    # The input subject directories or XNAT labels to process.
    parser.add_argument('input', nargs='+',
                        help='the AIRC DICOM subject directory to stage'
                             ' or XNAT session label to process')

    args = vars(parser.parse_args())
    nonempty_args = dict((k, v) for k, v in args.iteritems() if v != None)

    return nonempty_args.pop('input'), nonempty_args


if __name__ == '__main__':
    sys.exit(main())
