#!/usr/local/bin/perl
# atopojo.pl - Generate MUD inter-area topology as JSON
#
# Copyright 2015 David Meyer <[email protected]> +JMJ
# (License and documentation at bottom of file.)

use strict;
use warnings;
use Getopt::Std;
use File::Basename;
use JSON;


our (%AREA, %RMAREA, @RMLINK);


%FSM::STATE = (SKIP => 0,
              AREA => 1,
              ROOMS => 2,
              PENDRNAME => 3,
              PENDRDESC => 4,
              WAITDOOR => 5,
              PENDDDESC => 6,
              PENDDKW => 7,
              PENDDLKD => 8);
$FSM::state = $FSM::STATE{SKIP};

sub parse_are_fsm {
   my($afile, $aline) = @_;

   if ($FSM::state == $FSM::STATE{SKIP}) {
       if ($aline =~ /^#AREA ({\d+ \d+} \w+ )?(.*)~$/) {
           $FSM::areaname = $2;
#           my ($path, $base, $ext) = fileparse($afile, qr/\.[^.]*$/);
           $afile =~ m:(.*/)?(.*)\.[^.]*:;
           $FSM::areaid = $2;
           $AREA{$FSM::areaid} = {FILE => $afile, NAME => $FSM::areaname};
           $FSM::state = $FSM::STATE{AREA};
       }
   }

   elsif ($FSM::state == $FSM::STATE{AREA}) {
       if ($aline =~ /^#ROOMS$/) {
           $FSM::state = $FSM::STATE{ROOMS};
       }
       elsif ($aline =~ /^#$$/) {
           $FSM::state = $FSM::STATE{SKIP};
       }
   }

   elsif ($FSM::state == $FSM::STATE{ROOMS}) {
       if ($aline =~ /^#(\d+)$/) {
           $FSM::room = $1;
           $RMAREA{$FSM::room} = $FSM::areaid;
           $FSM::state = $FSM::STATE{PENDRNAME};
       }
       elsif ($aline =~ /^#0$/) {
           $FSM::state = $FSM::STATE{AREA};
       }
   }

   elsif ($FSM::state == $FSM::STATE{PENDRNAME}) {
       if ($aline =~ /~$/) {
           $FSM::state = $FSM::STATE{PENDRDESC};
       }
   }

   elsif ($FSM::state == $FSM::STATE{PENDRDESC}) {
       if ($aline =~ /~$/) {
           $FSM::state = $FSM::STATE{WAITDOOR};
       }
   }

   elsif ($FSM::state == $FSM::STATE{WAITDOOR}) {
       if ($aline =~ /^D(\d+)$/) {
           $FSM::exdir = $1;
           $FSM::state = $FSM::STATE{PENDDDESC};
       }
       elsif ($aline =~ /^S$/) {
           $FSM::state = $FSM::STATE{ROOMS}
       }
   }

   elsif ($FSM::state == $FSM::STATE{PENDDDESC}) {
       if ($aline =~ /~$/) {
           $FSM::state = $FSM::STATE{PENDDKW};
       }
   }

   elsif ($FSM::state == $FSM::STATE{PENDDKW}) {
       if ($aline =~ /~$/) {
           $FSM::state = $FSM::STATE{PENDDLKD};
       }
   }

   elsif ($FSM::state == $FSM::STATE{PENDDLKD}) {
       if ($aline =~ /^\w+ \w+ (\d+)$/) {
#           print "test: $1/$aline";
           $FSM::exdest = $1;
           push @RMLINK, [$FSM::room, $FSM::exdest];
           $FSM::state = $FSM::STATE{WAITDOOR};
       }
   }

   else {
       die "Invalid state processing file $afile line $.";
   }

}


our %OPTIONS = ();
getopts('f:', \%OPTIONS);

if (defined($OPTIONS{f})) {
   open(my $FLIST, "<", $OPTIONS{f}) or die "Can't open file $OPTIONS{f}: $!";
   my @afiles;
   while (<$FLIST>) {
       chop $_;
       if ($_ eq '$') {last;}
       push @afiles, $_;
   }
   foreach my $afile (@afiles) {
       open(my $AF, "<", $afile) or die "Can't open file $afile: $!";
       while (<$AF>) {
           parse_are_fsm($afile, $_);
       }
   }
}
else {
   while (<>) {
       parse_are_fsm($ARGV, $_);
   }
}

foreach my $area (keys %AREA) {
   print "AREA $area\t$AREA{$area}{FILE}\t$AREA{$area}{NAME}\n";
}
foreach my $rm (keys %RMAREA) {
   print "RMAREA $rm\t$RMAREA{$rm}\n";
}
foreach my $link (@RMLINK) {
   print "RMLINK ", join("\t", @$link), "\n";
}

exit 0

__END__

# Documentation #####################################################
=head1 NAME

template.pl - Perl script template (command line)

=head1 SYNOPSIS/USAGE

=head1 DESCRIPTION

Mark up code elements with C<>, file names with F<> (or C<> for
readability), command names with B<>. Also I<> for italics, U<> for
underline. Entities: E<lt> ('<'), E<gt> ('>').

=head1 OPTIONS

=item B<-o> I<value>, B<--option>=I<value>

=head1 RETURN VALUE

=head1 ERRORS

=head1 DIAGNOSTICS

=head1 EXAMPLES

=head1 ENVIRONMENT

=over 6

=item VARIABLE

Description of usage of environment variable C<VARIABLE>.

=back

=head1 FILES

=head1 BUGS, LIMITATIONS, AND CAVEATS

=head1 NOTES

=head1 AUTHOR

David Meyer <[email protected]>

=head1 HISTORY

=head1 COPYRIGHT AND LICENSE

Copyright 201x David Meyer

=head1 SEE ALSO



# Emacs control #####################################################
#Local variables:
#mode: perl
#End: