#!/usr/bin/perl

# TODO: texinfo fails on @cindex in title elements etc. *sigh*

use Pod::POM;
	
sub escape_texi($) {
   local $_ = shift;
   s/([\@\{\}])/\@$1/g;
   s/\n+/ /g;
   $_;
}

sub example {
   my $text = $_[0];
   $text =~ s/\n+$//;
   $text =~ s/([\@\{\}])/\@$1/g;

   "\n\n\@example\n"
   . $text
   . "\n\@end example\n\n";
}

my @nodes; # nodelist
my @ctx;   # curstack

sub out {
   $ctx[-1]{out} .= join "", @_;
}

sub TEX::view_seq_code { "\@t{$_[1]}" }
sub TEX::view_seq_bold { "\@strong{$_[1]}" }
sub TEX::view_seq_italic { "\@emph{$_[1]}" }

sub TEX::view_seq_space { escape_texi $_[1] }
sub TEX::view_seq_text { escape_texi $_[1] }

sub TEX::view_seq_link { $_[1] }
sub TEX::view_seq_index {
   "\n\@cindex $_[1]\n$_[1]"
}

*TXT::view_seq_code =
*TXT::view_seq_bold =
*TXT::view_seq_italic =
*TXT::view_seq_space =
*TXT::view_seq_text =
*TXT::view_seq_link =
*TXT::view_seq_index = sub { $_[1] };

my %ignore = (
   "SEE ALSO" => 1,
   "AUTHOR"   => 1,
);

sub parse_pod {
   my ($data) = @_;
   local $out;

   local $Pod::POM::DEFAULT_VIEW = TEX::;

   my $parser = new Pod::POM;
   my $pod = $parser->parse_text ($data)
      or die;

   my $walker; $walker = sub {
      my $n = $_[0];
      my $t = $n->type;

      if ($t eq "text") {
         out $n->text . "\n\@refill\n";

      } elsif ($t eq "pod") {
         $walker->($_) for $n->content;

      } elsif ($t eq "verbatim") {
         out example $n->text;

      } elsif ($t eq "head1") {

         return if $ignore{$n->title};
         
         out "\n\@section " . $n->title . "\n";
         $walker->($_) for $n->content;
         out "\n";

      } elsif ($t eq "head2") {
         out "\n\n\@subsection " . $n->title . "\n";
         $walker->($_) for $n->content;

      } elsif ($t eq "over") {
         out "\n\n\@itemize\n";
         $walker->($_) for $n->content;
         out "\@end itemize\n\n";

      } elsif ($t eq "item") {
         out "\n\n\@item\n" . $n->title . "\n\n";

         if ($n->title->present (TXT::) =~ /^\s*([a-zA-Z0-9\-\_]+)\s*=/) {
            out "\@cindex $1\n";
         }
         $walker->($_) for $n->content;

      } elsif ($t eq "begin") {
         local $Pod::POM::DEFAULT_VIEW = Pod::POM::View::Pod;
         my $format = $n->format;

         if ($format =~ /texinfo\s+header/) {
            $header = $n->content;
         } elsif ($format =~ /texinfo\s+footer/) {
            $footer = $n->content;
         } else {
            out $n->content;
         }

      } elsif ($t eq "for") {
         my $text = $n->text;

         if ($text =~ /^menu-begin/) {
            out "\n\@menu\n";

            push @ctx, {}; # dummy node

         } elsif ($text =~ /^menu-item (.*?)::\s+(.*)/) {
            my ($name, $desc) = ($1, $2);

            push @{ $ctx[-2]{menu} }, [$name, $desc];
            $ctx[-2]{width} = length $name if $ctx[-2]{width} < length $name;

            my $ctx = {
               name => $name,
               up   => $ctx[-2]{name},
            };
            push @nodes, $ctx;
            $ctx[-1] = $ctx;

         } elsif ($text =~ /^menu-end/) {
            pop @ctx;

            for (@{ $ctx[-1]{menu} }) {
               out sprintf "* %-*s %s\n", $ctx[-1]{width} + 2, "$_->[0]::", $_->[1];
            }

            out "\@end menu\n";

         } elsif ($text =~ /^include (\S+) (.*)/) {
            my ($type, $path) = ($1, $2);

            open my $x, "<$path" or die "$path: $!";
            my $data = do { local $/; <$x> };

            if ($type eq "pod") {
               out parse_pod ($data);
            } elsif ($type eq "text") {
               out $data;
            } elsif ($type eq "example") {
               out example $data;
            }

         } else {
            die "UNKNOWN for command <$text>\n";
         }

      } else {
         die "UNKNOWN NODE $t\n";
      }
   };

   $walker->($pod);
}

@ctx = @nodes = {
   up   => "(dir)",
   name => "Top",
};

parse_pod do { local $/; <> };

print $header;

for (0 .. $#nodes) {
   my $node = $nodes[$_];
   my $prev = $_ > 0 ? $nodes[$_-1] : undef;
   my $next = $nodes[$_+1];
   my $chapter = $node->{name} eq "Top" ? "Introduction" : $node->{name};

   print "\@node $node->{name},$next->{name},$prev->{name},$node->{up}\n\n",
         "\@chapter $chapter\n",
         "$node->{out}\n\n";
}

print $footer;

