#!/bin/env perl
#
# pstamp_queue_reqests.pl
# Query registered data stores for new postage stamp requests and add them to
# the database of pending requests.
#

use warnings;
use strict;

my $verbosity = 0;

use Sys::Hostname;
my $host = hostname();

if ($verbosity) {
    print STDERR "\n\n";
    print STDERR "Starting script $0 on $host\n\n";
}

use IPC::Cmd 0.36 qw( can_run run );

use PS::IPP::Metadata::Config;
use PS::IPP::Metadata::Stats;
use PS::IPP::Metadata::List qw( parse_md_list );

use PS::IPP::Config qw($PS_EXIT_SUCCESS
		       $PS_EXIT_UNKNOWN_ERROR
		       $PS_EXIT_SYS_ERROR
		       $PS_EXIT_CONFIG_ERROR
		       $PS_EXIT_PROG_ERROR
		       $PS_EXIT_DATA_ERROR
		       $PS_EXIT_TIMEOUT_ERROR
		       metadataLookupStr
		       metadataLookupBool
		       caturi
		       );

my $missing_tools;

my $pstamptool  = can_run('pstamptool')  or (warn "Can't find pstamptool"  and $missing_tools = 1);
my $dsproductls = can_run('dsproductls') or (warn "Can't find dsproductls" and $missing_tools = 1);
my $dsfilesetls = can_run('dsfilesetls') or (warn "Can't find dsfilesetls" and $missing_tools = 1);

if ($missing_tools) {
    warn("Can't find required tools.");
    exit ($PS_EXIT_CONFIG_ERROR);
}

my $mdcParser = PS::IPP::Metadata::Config->new; # Parser for metadata config files

my @dataStores;
#Look up the list of data stores to monitor
{
    my $command = "$pstamptool -datastore";
    my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
        run(command => $command, verbose => $verbosity);
    unless ($success) {
        die("Unable to perform pstamptool -datastore: $error_code >> 8");
    }

    if (@$stdout_buf == 0) {
        print STDERR "no data stores registered\n";
        exit 1;
    }
    my $metadata = $mdcParser->parse(join "", @$stdout_buf) or
        die("Unable to parse metdata config doc");

    my $ds = parse_md_list($metadata);

    @dataStores = @$ds;
}

if (! @dataStores) {
    print STDERR "no postage stamp data stores found\n";
    exit 1;
}

# loop over the data stores
foreach my $ds (@dataStores) {
    my $lastFileset;

    # skip any data stores that aren't enabled

    if ($ds->{state} ne "enabled") {
        next;
    }

    my $outProduct = $ds->{outProduct};
    my $ds_id = $ds->{ds_id};
    my @raw_output;
    {
        my $command = "$dsproductls --uri $ds->{uri}/index.txt --last_fileset $ds->{lastFileset}";
        my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
            run(command => $command, verbose => $verbosity);
        unless ($success) {
            die("Unable to perform $command: $error_code");
        }

        if (@$stdout_buf == 0) {
            print STDERR "no new request files in data store $ds_id\n";
            next;
        }
        @raw_output = @$stdout_buf;
    }

    foreach my $fs (@raw_output) {
        # split into lines
        my @lines = map {split "\n"} $fs;

        #
        # each line contains a fileset
        #
        foreach my $line (@lines) {
            # parse the line into fields split by whitespace
            my ($uri, $fs_name, $date, $type) = split " ", $line;
            $_ = $uri;
            # skip comment lines
            if (/^#.*/) {
                next;
            }

            my @out_buf;
            {
                my $command = "$dsfilesetls --uri $uri";
                my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
                    run(command => $command, verbose => $verbosity);
                unless ($success) {
                    die("Unable to perform $command: $error_code");
                }

                if (@$stdout_buf == 0) {
                    print STDERR "no file sets found\n";
                    next;
                }
                @out_buf = @$stdout_buf;
            }

            #
            # This is getting indented pretty far
            # Looks like we're going to need to learn about functions/subroutines :)
            #

            ## TODO: fail if there is more than one request file in the fileset
            foreach my $bit (@out_buf) {
                my @files = map {split "\n"} $bit;
                #
                # For each file in the fileset add a request
                #
                foreach my $file (@files) {
                    my ($req_uri, $fn, $size, $md5sum, $type, $chipname) = split " ", $file;

                    # skip comment lines
                    $_ = $req_uri;
                    if (/^#.*/) {
                        next;
                    }

                    {
                        my $command = "$pstamptool -addreq -uri $req_uri -ds_id $ds_id -out_fileset $outProduct/$fs_name";
                        my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
                            run(command => $command, verbose => $verbosity);
                        unless ($success) {
                                # XXX: what do we do now?
                                die("Unable to perform $command: $error_code");
                        }
                    }
                    $lastFileset = $fs_name;
                    # we only allow one request file per fileset
                    last;
                }
            }
        }
    }

    ## now update the data store table with the last_fileset
    if ($lastFileset) {
        # print "last fileset: $lastFileset\n";
        {
        my $command = "$pstamptool -ds_id $ds_id -moddatastore -last_fileset $lastFileset";
        my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
            run(command => $command, verbose => $verbosity);
            unless ($success) {
                die("Unable to perform pstamptool -moddatastore: $error_code");
            }
        }
    }
}

exit 0;
