#!/usr/bin/perl
use strict;
use warnings;
my($app_svnid) = '$HeadURL$ $LastChangedRevision$'; ## no critic (RequireInterpolationOfMetachars)
use lib substr(`ade-config ade_share_prefix`,0,-1) . '/include'; ## no critic (ProhibitBacktickOperators)
use ADE;
use lib substr(`fad-config fad_share_prefix`,0,-1) . '/include'; ## no critic (ProhibitBacktickOperators)
use FAD;
use Getopt::Long qw(:config no_ignore_case);
use Fatal qw( close unlink );  #  obviate checking close()'s return code

my(%mkfad_defined_errors) = (
    mkfad_err_access        => { fmt => '%s: can\'t %s' },
);

#  Options
my($opt_outfile, $opt_infile, $opt_nocrcs);

sub mkfad
{
    my($errstack_ref) = @_;
    my($rc, $in_handle, $out_handle);
    my(%data_store, $collected_info_ref);

    #  Set ADE options
    ADE::ade_err_registerdefderrs(\%mkfad_defined_errors);

    #  Defaults for options
    $opt_outfile = undef;
    $opt_infile = undef;
    $opt_nocrcs = undef;

    #  Register options
    if (($rc=ADE::ade_opt_register($errstack_ref, 'i:so:s', 'no-crcs,infile:s,outfile:s', 'main::mkfad_opt_handler_%s')) != $ADE::ADE_ERR_OK) {
        return($rc);
    }

    #  Register handler functions
    if (($rc=ADE::ade_msg_register($errstack_ref, \&mkfad_usage, \&mkfad_version, \&mkfad_listpaths)) != $ADE::ADE_ERR_OK) {
        return($rc);
    }

    #  Process options
    ADE::ade_err_debug($errstack_ref, 10, 'mkfad: processing options ...');
    if (($rc=ADE::ade_opt_process($errstack_ref)) != $ADE::ADE_ERR_OK) {
        return($rc);
    }

    #  Process arguments
    ADE::ade_msg_usage($errstack_ref) if (defined $ARGV[0]);

    $rc = 0;
    #  Open file list if specified
    if (defined $opt_infile) {
        if (($rc=ADE::ade_fcm_openreadcompressed($errstack_ref, $opt_infile, \*IN_HANDLE)) != $ADE::ADE_ERR_OK) {
            ADE::ade_err_error($errstack_ref, 'mkfad_err_access', $opt_infile, 'open');
            return($rc);
        }
        $in_handle = \*IN_HANDLE;
    } else {
        $in_handle = \*STDIN;
    }

    #  Slurp file list, generate FAD records, and store in internal store
    while (<$in_handle>) {
        chomp;
        return($rc) if (($rc=FAD::fad_collect_info($errstack_ref, $_, $opt_nocrcs, \$collected_info_ref)) != $ADE::ADE_ERR_OK);
        return($rc) if (($rc=FAD::fad_insert_info($errstack_ref, \%data_store, $collected_info_ref)) != $ADE::ADE_ERR_OK);
    }

    #  Close input file if necessary
    if (defined $opt_infile) {
        close IN_HANDLE;
    }

    #  Open output file if specified
    if (defined $opt_outfile) {
        ADE::ade_err_debug($errstack_ref, 10, "mkfad: registering outfile $opt_outfile ...");
        ADE::ade_tmp_registerfile($errstack_ref, $opt_outfile);
        if (($rc=ADE::ade_fcm_openwritecompressed($errstack_ref, $opt_outfile, \*OUT_HANDLE)) != $ADE::ADE_ERR_OK) {
            ADE::ade_err_error($errstack_ref, 'mkfad_err_access', $opt_outfile, 'open');
            return($rc);
        }
        $out_handle = \*OUT_HANDLE;
    } else {
        ADE::ade_err_debug($errstack_ref, 10, 'mkfad: outfile is stdout');
        $out_handle = \*STDOUT;
    }

    #  Print all records to the output handle.
    ADE::ade_err_debug($errstack_ref, 10, 'mkfad: dumping records to outfile ...');
    if (($rc=FAD::fad_dump($errstack_ref, $out_handle, \%data_store)) != $ADE::ADE_ERR_OK) {
        return($rc);
    }

    #  Close output file if necessary
    if (defined $opt_outfile) {
        close OUT_HANDLE;
        ADE::ade_err_debug($errstack_ref, 10, "mkfad: deregistering $opt_outfile");
        ADE::ade_tmp_deregisterfile($errstack_ref, $opt_outfile);
    }

    #  Now that we have finished with the FAD store, we can clear it of all records.
    undef %data_store;

    #  Ensure sensible return code
    return($ADE::ADE_ERR_OK);
}

sub mkfad_opt_handler_i  ## no critic (RequireArgUnpacking)
{
    return(mkfad_opt_handler_infile(@_));
}

sub mkfad_opt_handler_o  ## no critic (RequireArgUnpacking)
{
    return(mkfad_opt_handler_outfile(@_));
}

sub mkfad_opt_handler_no_crcs
{
    my($errstack_ref) = @_;

    $opt_nocrcs = 1;

    return($ADE::ADE_ERR_OK);
}

sub mkfad_opt_handler_infile
{
    my($errstack_ref, $infile) = @_;

    $opt_infile = $infile;

    return($ADE::ADE_ERR_OK);
}

sub mkfad_opt_handler_outfile
{
    my($errstack_ref, $outfile) = @_;

    $opt_outfile = $outfile;

    return($ADE::ADE_ERR_OK);
}

sub mkfad_version
{
    my($errstack_ref, $version_text_ref) = @_;

    return(ADE::ade_smf_extractversionfromsvnstring($errstack_ref, $app_svnid, $version_text_ref));
}

sub mkfad_listpaths
{
    my($errstack_ref, $pathlist_text_ref) = @_;
    my($rc);

    ${$pathlist_text_ref} = undef;

    return($ADE::ADE_ERR_OK);
}

sub mkfad_usage
{
    my($errstack_ref, $usage_text_ref, $passno) = @_;

    if ($passno == 1) {
        ${$usage_text_ref} = undef;
    } elsif ($passno == 2) {
        ${$usage_text_ref} = "         -i <file> | --infile=<file>         read file list from <file>\n" .
                             "         -o <file> | --outfile=<file>        send output to <file>\n" .
                             "                     --no-crcs               suppress content checksums\n";
    }

    return($ADE::ADE_ERR_OK);
}

ADE::ade_gep_main(\&mkfad);
