#!perl -w
use strict;

use vars qw(%CmdName %OptName);

BEGIN {
  %CmdName = map {/^\d/ ? chr($_) : $_} (
      0 => 'IS'  ,
      1 => 'SEND',
    240 => 'SE'  , # subnegotiation end
    241 => 'NOP' ,
    242 => 'DM'  , # Data Mark - not implemented
    243 => 'BRK' , # Break - not implemented
    244 => 'IP'  , # Interrupt Process
    245 => 'AO'  , # Abort output - not implemented
    246 => 'AYT' , # Are You There
    247 => 'EC'  , # Erase character
    248 => 'EL'  , # Erase Line
    249 => 'GA'  , # go ahead
    250 => 'SB'  , # subnegotiation begin
    251 => 'WILL', # \
    252 => 'WONT', #  \ option negotiation 
    253 => 'DO'  , #  /
    254 => 'DONT', # /
    255 => 'IAC' , # Interpret As Command
  );
  foreach (keys %CmdName) {
    eval "sub $CmdName{$_} () {chr(" . ord($_) . ")}"; die $@ if $@;
  }
  %OptName = map {/^\d/ ? chr($_) : $_} (
     1 => 'ECHO',
     6 => 'TIMING-MARK',
    24 => 'TERMINAL-TYPE',
    31 => 'NAWS',
  );
  foreach (keys %OptName) {
    my $name = $OptName{$_};
    $name =~ tr/-/_/;
    eval "sub OPT_$name () {chr(" . ord($_) . ")}"; die $@ if $@;
  }
}

use Net::Telnet;
use Chatbot::Eliza;

my $user = 'Eliza';
my $pass = 'zickelgork';
my $EL = "\cJ";

my ($s, $exit);
RESTART:
print "Connecting\n";
eval {$s = IO::Socket::INET->new(
  Proto => 'tcp',
  PeerAddr => 'imax.reid.loc',
  PeerPort => '4000',
) or do {sleep 10; goto RESTART if $! =~ /Bad file descriptor/; die $!};
};
if ($@) {
  sleep 10;
  $@ =~ /Socket is not connected/ and goto RESTART;
  die $@;
}
$s->autoflush(1);

$s->print(IAC.WONT.OPT_TERMINAL_TYPE);
$s->print("$user$EL");
$s->print("$pass$EL");
$s->print("1$EL");

my $bot = Chatbot::Eliza->new();

sub msend { $s->print(@_, $EL) }

ai_startup();

MAIN: while (<$s>) {
  defined $_ or last;
  tr/\x00-\x1F\x7F-\xFF//d;
  print "<<$_\n";
  ai_process_line();
}
$s->close;

###################################################################

my ($mode, %inventory, %requests);

sub ai_startup {
  $mode = '';
  msend "i";  
}

sub ai_process_line {
  if ($mode eq 'inventory') {
    if (/^  (.*)/) {
      $inventory{$1}++;
      print "$1++";
    } else {
      $mode = '';
    }
  } else {

    if (/^(\w.*) (?:say|ask)s, "(.*)"$/mg) {
      my $who = $1;
      local $_ = $2;
      print "Got $who: $_\n";
  
      if ($bot->_testquit($_)) {
        print "Quitting\n";
        msend "quit";
        msend "0";
      } elsif (/buy (.*)/) {
        my $item = $1;
        if (exists $inventory{$1}) {
          msend "'I have $inventory{$1} of that.";
        } else {
          msend "'I don't have $1.";
        }
      } else {
        my $reply = $bot->transform($_);
        print "Replying $reply\n";
        msend "'$reply$EL";
      }

    } elsif (/^(.*) has arrived from the north\.$/) {
      msend "'Hello, $1";
    }
  }
}