#!/usr/bin/env python
# coding: utf-8

from __future__ import print_function
from __future__ import unicode_literals

import os
import argparse
import subprocess


def argparser():
    parser = argparse.ArgumentParser()
    # parser.add_argument('command', nargs='?',
    #                     help="Command to use for the job (in passive mode)")
    parser.add_argument('command', nargs=argparse.REMAINDER,
                        help="Command to use for the job (in passive mode)")
    parser.add_argument('-n', '--name',
                        help="Name to give to the job")
    parser.add_argument('-d', '--directory',
                        help="Directory in which will be stored oarsub outputs")
    parser.add_argument('-b', '--besteffort', action="store_true",
                        help="Launch job in besteffort mode")
    parser.add_argument('-t', '--time', default="10",
                        help="Estimated maximum duration of the job (format: h[:m[:s]]) (default: %(default)s)")
    parser.add_argument('-g', '--gpu', action="store_true",
                        help="If True, reserves only cores with GPUs")
    parser.add_argument('-c', '--core', default=1, type=int,
                        help="Number of cores to reserve. (default: %(default)s)")
    parser.add_argument('-H', '--host', nargs="+", default=[],
                        help="Name of the hosts (SQL 'LIKE' syntax accepted)")
    parser.add_argument('-I', '--ignore-host', nargs="+", default=[],
                        help="Name of the hosts to ignore (SQL 'NOT LIKE' syntax accepted)")
    parser.add_argument('-i', '--interactive', action="store_true",
                        help="Launch job in interactive mode")
    parser.add_argument('-C', '--checkpoint', type=int, metavar="SECONDS",
                        help="Enable checkpoint signals with the given delay (in seconds)")
    parser.add_argument('-r', '--run', action="store_true",
                        help="Run the command")
    parser.add_argument('-a', '--anterior',
                        help="Anterior job id that must be terminated to start this new one")
    args = parser.parse_args()

    return args


def prepare_oarsub(gpu, hosts, core, time,
                   ignore_hosts=[],
                   command=None,
                   interactive=False,
                   name=None, output_directory=None,
                   besteffort=False,
                   checkpoint=None, anterior=None):
    oar_cmd = ["oarsub"]
    oar_cmd.append("-p")
    properties = ""
    if gpu:
        properties += "(gpu IS NOT NULL)"
    else:
        properties += "(gpu IS NULL)"
    if hosts:
        properties += " AND ("
        for idx, host in enumerate(hosts):
            if idx != 0:
                properties += " OR "
            properties += "host LIKE '{}'".format(host)
        properties += ")"
    if ignore_hosts:
        for host in ignore_hosts:
            properties += " AND host NOT LIKE '{}'".format(host)
    properties += ""
    oar_cmd.append(properties)

    oar_cmd.append("-l")
    time = time.split(':')
    hour = time[0]
    minutes = time[1] if len(time) >= 2 else "00"
    seconds = time[2] if len(time) >= 3 else "00"
    ressources = "core={},walltime={}:{}:{}".format(core, hour, minutes, seconds)
    oar_cmd.append(ressources)

    if name is not None:
        oar_cmd.append("-n")
        oar_cmd.append(name)
        directory = output_directory + "/" if output_directory is not None else ""
        oar_cmd.append("-O")
        oar_cmd.append("{}{}.%jobid%.stdout".format(directory, name))
        oar_cmd.append("-E")
        oar_cmd.append("{}{}.%jobid%.stderr".format(directory, name))

    if besteffort:
        oar_cmd.extend(["-t", "besteffort", "-t", "idempotent"])

    if checkpoint is not None:
        oar_cmd.extend(["--checkpoint", checkpoint])

    if anterior is not None:
        oar_cmd.extend(["-a", anterior])

    if interactive:
        oar_cmd.append('-I')
    else:
        job_command = command if isinstance(command, str) else " ".join(command)
        oar_cmd.append(job_command)
    return oar_cmd


def run_oarsub(command, print_cmd=False, fake_run=False, return_output=False):
    if print_cmd:
        print(subprocess.list2cmdline(command))
    if fake_run:
        return None
    if not return_output:
        subprocess.call(command)
        return None
    return subprocess.check_output(command).decode("utf8")


def main():
    args = argparser()

    if args.directory is not None and not os.path.isdir(args.directory) and args.run:
            raise RuntimeError("'{}' is not a directory!".format(args.directory))

    oar_command = prepare_oarsub(args.gpu, args.host, args.core, args.time,
                                 ignore_hosts=args.ignore_host,
                                 command=args.command,
                                 interactive=args.interactive,
                                 name=args.name, output_directory=args.directory,
                                 besteffort=args.besteffort, checkpoint=args.checkpoint,
                                 anterior=args.anterior)

    run_oarsub(oar_command, print_cmd=True, fake_run=not args.run)


if __name__ == '__main__':
    main()