#! /usr/bin/env perl

use Getopt::Long;
use IO::File;
use strict;

my $service_host = 'localhost';
my $service_port = 8443;
my $scheduler = 'Fork';
my $gridftp_port = -1;
my $streaming = 0;
my $test_dir = 'submit_test';
my $help = 0;
my $script_name = '';
my $debug = 0;
my @test_types = ();

GetOptions("host=s" => \$service_host,
           "port=i" => \$service_port,
           "scheduler=s" => \$scheduler,
           "gridftp-port=i" => \$gridftp_port,
           "streaming" => \$streaming,
           "dir=s" => \$test_dir,
           "debug" => \$debug,
           "help|h" => \$help);

if (exists $ARGV[0]) {
    $script_name = $ARGV[0];
}

if ($help || $script_name eq '') {
    print <<EOF;
Usage: $0 [OPTIONS] test-script-name
Command-Line Options:
    -host HOSTNAME                      Name of Service container host.
                                        [Default: localhost].
    -port PORT                          Use PORT as the TCP port to contact
                                        the service container. [Default: 8443]
    -scheduler SCHEDULER                Use SCHEDULER as the GRAM Type for the
                                        tests. If Multi, then only multirequest
                                        tests will be done. [Default: Fork].
    -gridftp-port PORT                  Use PORT as the TCP port of the local
                                        GridFTP server. This will be used to
                                        stage output in some tests.  If this
                                        is not set, then tests which
                                        require file staging will not be done.
                                        [Default: not set]
    -streaming                          Enable file streaming of output
                                        [Default: not set]
    -dir DIRECTORY                      Relative path to directory containing
                                        test RSLs [Default: submit_test].
    -debug                              Print debug messages
EOF
    exit(1);
}

if ($service_host eq 'localhost') {
    push (@test_types, 'Local');
}
if ($streaming != 0) {
    push (@test_types, 'Streaming');
}

if ($gridftp_port != -1) {
    push (@test_types, 'Staging');
}


# test attributes
#    TestName
#    JobType: exec | multi (default exec)
#    Stdin: local | staged | none (default none)
#    Stdout: yes | no (default no)
#    Stderr: yes | no (default no)
#    FaultType: none | {namespace}FaultType (default none)
#    OutputVar: VAR VALUE (default none)
#    ExitCode: <int> [default -1 is ignore]

#use constant {
# JOBTYPE
my $JOBTYPE_EXEC = 0;
my $JOBTYPE_MULTI = 1,
# STDIN
my $STDIN_NONE = 0;
my $STDIN_LOCAL = 1;
my $STDIN_STAGED = 2;
#};

my $script = new IO::File($script_name, ">");
$script->print(<<EOF);
ScriptName      $script_name

ServiceHost     $service_host
ServicePort     $service_port
SchedulerType   $scheduler
EOF

if ($gridftp_port != -1) {
    $script->print("GridFTPPort     $gridftp_port\n");
}

$script->print("\n");

my $test_num = 0;
foreach (<$test_dir/*.xml>) {
    my $test_file = $_;
    my $fh = new IO::File($_, '<');
    my $test_name = '';
    my $job_type = 'exec';
    my $stdin = $STDIN_NONE;
    my $stdout_local = 0;
    my $stdout_stream = 0;
    my $stdout_stage = 0;
    my $stderr = 0;
    my $fault = '';
    my $jobtype = $JOBTYPE_EXEC;
    my $exit_code = -1;
    my $skip = '0';
    my @stdout_var = ();

    $test_file =~ s/.*\/([^\/]+).xml/$1/;

    while (<$fh>) {
        if (/TestName:\s*(.*)/i) {
            $test_name = $1;
        } elsif (/^<multiJob>/) {
            $job_type = 'multi';
        } elsif (/^Stdin:\s*(.*)/i) {
            if ($1 eq 'local') {
                $stdin = $STDIN_LOCAL;
            } elsif ($1 eq 'staged') {
                $stdin = $STDIN_STAGED;
            } elsif ($1 eq 'none') {
                $stdin = $STDIN_NONE;
            } else {
                print "Unknown stdin mode: $1\n" if $debug;
            }
        } elsif (/^Stdout:\s*(.*)/i) {
            if ($1 eq 'yes') {
                $stdout_local = 1;
                $stdout_stream = 1;
                $stdout_stage = 1;
            } elsif ($1 eq 'no') {
                $stdout_local = 0;
                $stdout_stream = 0;
                $stdout_stage = 0;
            } elsif ($1 =~ m/stream/i) {
                $stdout_local = 0;
                $stdout_stream = 1;
                $stdout_stage = 0;
            } elsif ($1 =~ m/staged/i) {
                $stdout_local = 0;
                $stdout_stream = 0;
                $stdout_stage = 1;
            } else {
                print "Unknown stdout mode: $1\n" if $debug;
            }
        } elsif (/^Stderr:\s*(.*)/i) {
            if ($1 eq 'yes') {
                $stderr = 1;
            } elsif ($1 eq 'no') {
                $stderr = 0;
            } else {
                print "Unknown stderr mode: $1\n" if $debug;
            }
        } elsif (/^FaultType:\s*(.*)/i) {
            $fault = $1;
        } elsif (/^OutputVar:\s*(.*)/i) {
            push(@stdout_var, $1);
        } elsif (/^ExitCode:\s*(\d+)/i) {
            $exit_code = $1;
        } elsif (/^Skip:\s*(.+)/i) {
            $skip = $1;
        }
    }

    $test_num++;
    if ($test_name eq '') {
        $test_name = "Test $test_num";
    }

    if ($jobtype == $JOBTYPE_MULTI && $scheduler ne 'multi') {
        print STDERR "Skipping \"$test_name\" because:\n"
           .  "it's a multi job and my scheduler is $scheduler\n" if $debug;
        next;
    } elsif ($stdin == $STDIN_LOCAL && $service_host ne 'localhost') {
        print STDERR "Skipping \"$test_name\" because:\n"
            . "it requires local stdin and jobs will run on $service_host\n"
            if $debug;
        next;
    } elsif ($stdin == $STDIN_STAGED && $gridftp_port == -1) {
        print STDERR "Skipping \"$test_name\" because:\n"
            . "it requires staging and staging is not enabled\n"
            if $debug;
        next;
    } elsif ($skip ne '0') {
        if ($skip =~ m/yes/i) {
            print STDERR  "Skipping \"$test_name\" because:\n"
                . "skip is set to yes.\n"
                if $debug;
            next;
        } elsif ($skip =~ m/$scheduler/i) {
            print STDERR  "Skipping \"$test_name\" because:\n"
                . "skip argument matches the scheduler type.\n";
            next;
        }
    }

    my $stdout = $stdout_local || $stdout_stream || $stdout_stage;

    foreach my $test_type (@test_types) {
        if ($exit_code == -1 && $fault eq '' && $stdout != 0) {
            if (($test_type eq 'Local' && $stdout_local != 0) ||
                    ($test_type eq 'Streaming' && $stdout_stream != 0) ||
                    ($test_type eq 'Staging' && $stdout_stage != 0)) {
                $script->print("TestName         $test_name ($test_type)\n");
                $script->print("OutputType       $test_type\n");
            } else {
                next;
            }
        } else {
            $script->print("TestName         $test_name\n");
        }
        foreach (@stdout_var) {
            $script->print("StdOutVar $_\n");
        }
        if ($fault ne '' || $exit_code != -1) {
            $script->print("ShouldFail       yes\n");
        }
        if ($fault ne '') {
            $script->print("FaultType        $fault\n");
        }
        if ($exit_code != -1) {
            $script->print("ExitCode         $exit_code\n");
        }
        $script->print("RslFile          $test_file\n\n");

        if (($stdout == 0 && $stderr == 0)
            || $exit_code != -1 || $fault ne '') {
            last;
        }
    }
}
$script->close();
