#!/usr/bin/perl
use Getopt::Std;

# Test for an interactive shell.
#
my $gInteractive = ( -t STDIN && -t STDOUT );

my %shellCommands = (
    'quit' => { pkg => 'Quit', help => 'Quit the shell' },
    'exit' => { pkg => 'Quit', },
    'help' => { pkg => 'Help', help => 'Display this message' },
);

# Parse the command-line options.
#
my %gOptions;
_parseCommandLine( \%gOptions );

while ( my $command = _getCommand() ) {
    $command->execute();
}

sub _getCommand {

    # Print a prompt if we're in interactive mode...
    #
    print STDERR "> " if $gInteractive;

    # Read in a command string from STDIN.
    #
    my $cmdString = <STDIN>;
    chomp $cmdString;

    # Following the usual convention, any string that begins with
    # a '/' is assumed to be a direct shell command.
    #
    my $command;
    if ( '/' eq substr( $cmdString, 0, 1 ) ) {
        $command = _shellCommand($cmdString);
    } else {
        $command = _rpsCommand($cmdString);
    }
    if ( !$command ) {
        $command = Error->new( command => $cmdString );
    }

    return $command;
}

sub _shellCommand {
    my ($cmdString) = @_;
    my $noSlash = substr( $cmdString, 1 );

    my ( $token, @args ) = split( ' ', $noSlash );
    my $cmd = $shellCommands{$token};
    if ($cmd) {
        return $cmd->{pkg}->new( args => \@args );
    }

    return undef;
}

sub _rpsCommand {
    my ($cmdString) = @_;

    return undef;
}

sub _parseCommandLine {
    my ($settings) = @_;

    # Don't have any, yet...
    #

    #    my %opt;
    #    getopts('r:c:V:', \%opt);
    #
    #    if (! $opt{r} || ! $opt{c})
    #    {
    #        _usage();
    #        exit(1);
    #    }
    #    $settings->{runID} = $opt{r};
    #    $settings->{clientID} = $opt{c};
    #
    #    if (defined $opt{V})
    #    {
    #        $gVerbosityLevel = $opt{V};
    #    }
}

sub _usage {
    print STDERR "\nusage: $0\n";
    print STDERR "\n";
}

# -------
# We'll use this package for the shell commands (and the Error).
#
package BaseCommand;

sub new {
    my ( $class, %args ) = @_;
    my $self = bless {}, $class;
    return $self->_init(%args);
}

sub _init {
    my ( $self, %args ) = @_;

    return $self;
}

sub execute {
    my ($self) = @_;

}

# ----------
package Quit;
use base 'BaseCommand';

sub execute {
    my ($self) = @_;
    exit(0);
}

package Error;
use base 'BaseCommand';

sub _init {
    my ( $self, %args ) = @_;

    $self->{command} = $args{command};

    return $self;
}

sub execute {
    my ($self) = @_;

    print STDERR "ERROR: Unknown command '" . $self->{command} . "' \n";
    print STDERR "Try '/help' at the prompt for a list of valid shell commands\n" if $gInteractive;
}

package Help;
use base 'BaseCommand';

sub execute {
    my ($self) = @_;

    print STDERR "\nValid Commands:\n\n";

    my @commands = keys %shellCommands;
    foreach $cmdKey (@commands) {
        my $cmd = $shellCommands{$cmdKey};
        if ( $cmd->{help} ) {
            print STDERR "/$cmdKey : " . $cmd->{help} . "\n";
        }
    }

    print STDERR "\n";
}

1;
