#!/usr/bin/perl
use warnings;
use strict;
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(`js-config js_share_prefix`,0,-1) . '/include';    ## no critic (ProhibitBacktickOperators)
use JS;
use experimental 'smartmatch';
use IPC::SysV qw(IPC_PRIVATE IPC_RMID IPC_CREAT S_IRUSR S_IWUSR);
use Storable;

my(%jsm_defined_errors) = (
    'jsm_err_misc' => { fmt => '%s' },
);

#  Options

#  Other globals

sub jsm
{
    my($errstack_ref) = @_;
    my($rc, $jsd_pid, $running_flag, $lock_file, %message_hash, %reply_hash, $server_name);

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

    #  Defaults for options
    #  (identical line in jsd, jsm, jsq).

    #  Register options
    if (($rc=ADE::ade_opt_register($errstack_ref, '', '', 'main::jsm_opt_handler_%s')) != $ADE::ADE_ERR_OK) {
        return($rc);
    }

    #  Register handler functions
    if (($rc=ADE::ade_msg_register($errstack_ref, \&jsm_usage, \&jsm_version, \&jsm_listpaths)) != $ADE::ADE_ERR_OK) {
        return($rc);
    }

    #  Process options
    if (($rc=ADE::ade_opt_process($errstack_ref)) != $ADE::ADE_ERR_OK) {
        return($rc);
    }

    #  Process arguments

    #  Sanity checks and derivations
    if (($rc=JS::get_server_name($errstack_ref, \$server_name)) != $ADE::ADE_ERR_OK) {
        return($rc);
    }
    $lock_file = "$ADE::ADE_TMP_DIR/jsd-$server_name.lock";

    #  Guts
    if (($rc=ADE::ade_lck_checklock($errstack_ref, $lock_file, \$jsd_pid, \$running_flag)) != $ADE::ADE_ERR_OK) {
        ADE::ade_err_debug($errstack_ref, 20, 'jsm: ade_lck_checklock failed');
        return($rc);
    }
    if (!$running_flag) {
        ADE::ade_err_error($errstack_ref, 'jsm_err_misc', 'jsm: not running (hint: did you start it? is JS_NAME set correctly?)');
        return($ADE::ADE_ERR_FAIL);
    }

    if (($rc=list_to_hash($errstack_ref, \@ARGV, \%message_hash)) != $ADE::ADE_ERR_OK) {
        return($rc);
    }

    #  Error messages from here are to use whatever $PROGNAME is (jss or jsc).
    ADE::ade_app_set_progname($errstack_ref, $ENV{'PROGNAME'}) if $ENV{'PROGNAME'};

    if (($rc=JS::send_message_hash_and_read_reply_hash($errstack_ref, $server_name, \%message_hash, \%reply_hash)) != $ADE::ADE_ERR_OK) {
        return($rc);
    }

    #  If the server passed text back then display it.
    print $reply_hash{'stdout'} if $reply_hash{'stdout'};
    print STDERR $reply_hash{'stderr'} if $reply_hash{'stderr'};
    ADE::ade_err_info($errstack_ref, $reply_hash{'info'}) if $reply_hash{'info'};

    #  If the server raised a client-side error then handle that.
    if ($reply_hash{'rc'} != $ADE::ADE_ERR_OK) {
        #  Copy everything on the client error stack to the real error stack.
        @{$errstack_ref} = @{$reply_hash{'errstack-ref'}};
        return($reply_hash{'rc'});
    }

    #  Tidy up
    return ($ADE::ADE_ERR_OK);
}

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

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

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

    #${$pathlist_text_ref} = '';

    return($ADE::ADE_ERR_OK);
}

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

    if ($passno == 1) {
        ${$usage_text_ref} = "\n";
    } elsif ($passno == 2) {
        ${$usage_text_ref} = '';
    }

    return($ADE::ADE_ERR_OK);
}

sub list_to_hash
{
    my($errstack_ref, $list_ref, $hash_ref) = @_;
    my($key, $val);

    %{$hash_ref} = ();
    foreach my $item (@{$list_ref}) {
        if (!(($key,$val) = ($item=~/^([^=]+)=(.*)$/))) {
            ADE::ade_err_error($errstack_ref, 'jsm_err_misc', "$item: failed to parse");
            return($ADE::ADE_ERR_FAIL);
        }
        ADE::ade_err_debug($errstack_ref, 10, "list_to_hash: key=$key, val=$val");
        ${$hash_ref}{$key} = $val;
    }

    return($ADE::ADE_ERR_OK);
}

ADE::ade_gep_main(\&jsm);
