#!/usr/bin/perl -w

use strict;
use Getopt::Long;

# directory divider
my $dd = '/';
my $destdir='.';
my $title="HelpSet";
my $lang="en";

my $appname;
my $dictionary;
my $toc;
my $idx;

# process command line options

unless (&GetOptions("dd=s"    => \$dd,
                    "dir=s"   => \$destdir,
                    "title=s" => \$title,
                    "lang=s"  => \$lang,
                    "dict=s"  => \$dictionary,
                    "toc=s"   => \$toc,
                    "idx=s"   => \$idx,
                    "appname=s" =>\$appname))
{
   &usage();
   exit 1;
}

unless (defined($toc))
{
   print "Missing TOC file\n";
   &usage();
}

unless (defined($idx))
{
   print "Missing IDX file\n";
   &usage();
}

unless ($#ARGV == 0)
{
   print "Missing basename\n";
   &usage();
}

my $basename = $ARGV[0];

unless (defined($appname))
{
   $appname = $basename;
}

if (defined($dictionary))
{
   if (open FD, $dictionary)
   {
      while (<FD>)
      {
         if (m/help.handbook=(.+)/)
         {
            $title = $1;

            $title=~s/\\1/$appname/g;
         }
         elsif (m/xml.lang=(.+)/)
         {
            $lang=$1;
         }
      }

      close FD;
   }
   else
   {
      print STDERR "Can't open dictionary '$dictionary': $!\n";
   }
}

my %map=();

&load_tmp_map();

&load_index($idx);

&do_helpset();
&do_toc($toc);
&do_map();

sub usage{
   print "$!\n";
   print "Usage:\n";
   print "$0 [-dict <dictionary> -dd <directory divider> -dir <directory> -title <title> -lang <language> -appname <application name>] -idx <idx file> -toc <toc file> <basename>\n";
}

sub load_tmp_map{
   if (open MAP, "$basename/Map.tmp")
   {
      while (<MAP>)
      {
         if (m/<mapID target=\"(.*)\" url=\"(.*)\"\s*\/>/)
         {
            $map{$1}=$2;
         }
      }
   }
}

sub load_index{
   my($filename) = @_;
   my(@unsorted);
   my($j) = 0;

   open IDX, $filename or die "Can't open '$filename': $!\n";

   while (<IDX>)
   {
      if (s/^<([^>]*)><(\d+)>//)
      {
         my $target = $1;
         my $n = $2;

         if ($n > 4)
         {
            die "Index nested too deep on line $. (n=$n)\n";
         }

         if ($n < 1)
         {
            die "At least one index level required on line $. (n=$n)\n";
         }

         $map{$target}=$target;

         if ($n==1)
         {
            if (m/^<(.*)>$/)
            {
               $unsorted[$j++] = "<$1>##$target";
            }
            else
            {
               die "1 index level expected on line $.";
            }
         }
         elsif ($n==2)
         {
            if (m/^<(.*)><(.*)>$/)
            {
               my $item=$1;
               my $subitem=$2;

               $unsorted[$j++] = "<$item><$subitem>##$target";
            }
            else
            {
               die "2 index levels expected on line $.";
            }
         }
         elsif ($n==3)
         {
            if (m/^<(.*)><(.*)><(.*)>$/)
            {
               my $item       = $1;
               my $subitem    = $2;
               my $subsubitem = $3;

               $unsorted[$j++] = "<$item><$subitem><$subsubitem>##$target";
            }
            else
            {
               die "3 index levels expected on line $.";
            }
         }
         elsif ($n==4)
         {
            if (m/^<(.*)><(.*)><(.*)><(.*)>$/)
            {
               my $item       = $1;
               my $subitem    = $2;
               my $subsubitem = $3;
               my $subsubsubitem = $4;

               $unsorted[$j++] = "<$item><$subitem><$subsubitem><$subsubsubitem>##$target";
            }
            else
            {
               die "4 index levels expected on line $.";
            }
         }
      }
   }

   close IDX;

   for (my $i = 0; $i <= $#unsorted; $i++)
   {
      if ($unsorted[$i]=~m/<(.+)><(.+)><(.+)>##/)
      {
         my $item    = $1;
         my $subitem = $2;

         # is there a <$item>##

         my $foundit = 0;

         for (my $j = 0; $j <= $#unsorted; $j++)
         {
            if ($unsorted[$j]=~m/<$item>##/)
            {
               $foundit = 1;
               last;
            }
         }

         unless ($foundit)
         {
            $unsorted[$#unsorted+1] = "<$item>##";
         }

         # is there a <$item><$subitem>##

         $foundit = 0;

         for (my $j = 0; $j <= $#unsorted; $j++)
         {
            if ($unsorted[$j]=~m/<$item><$subitem>##/)
            {
               $foundit = 1;
               last;
            }
         }

         unless ($foundit)
         {
            $unsorted[$#unsorted+1] = "<$item><$subitem>##";
         }
      }
      elsif ($unsorted[$i]=~m/<(.+)><(.+)>##/)
      {
         my $item    = $1;

         # is there a <$item>##

         my $foundit = 0;

         for (my $j = 0; $j <= $#unsorted; $j++)
         {
            $unsorted[$j]=~m/^<(.+)>##/;

            if ($1 eq $item)
            {
               $foundit = 1;
               last;
            }
         }

         unless ($foundit)
         {
            $unsorted[$#unsorted+1] = "<$item>##";
         }
      }
   }

   my @sorted = sort {$a cmp $b} @unsorted;

   open XMLIDX, ">$destdir$dd${basename}Index.xml"
      or die "Can't open '$destdir$dd${basename}Index.xml': $!";

   print XMLIDX "<?xml version='1.0' encoding='ISO-8859-1' ?>\n";
   print XMLIDX "   <!DOCTYPE index\n";
   print XMLIDX "     PUBLIC \"-//Sun Microsystems Inc.//DTD JavaHelp Index Version 2.0//EN\"\n";
   print XMLIDX "     \"http://java.sun.com/products/javahelp/index_2_0.dtd\">\n\n";

   print XMLIDX "<index version=\"2.0\">\n";

   for (my $i = 0; $i <= $#sorted; $i++)
   {
      if ($sorted[$i]=~m/^<(.+)><(.+)><(.+)>##(.+)?$/)
      {
         my $target= $4;
         my $text = $3;

         if ($target)
         {
            print XMLIDX "         <indexitem text=\"$text\" target=\"$target\"/>\n";
         }
         else
         {
            print XMLIDX "         <indexitem text=\"$text\"\"/>\n";
         }
      }
      elsif ($sorted[$i]=~m/^<(.+)><(.+)>##(.+)?$/)
      {
         my $target= $3;
         my $text = $2;

         if ($i > 0 and $sorted[$i-1]=~m/^<([^>]+)><([^>]+)></)
         {
            print XMLIDX "      </indexitem>\n";
         }

         if ($i < $#sorted and $sorted[$i+1]=~m/^<([^>]+)><([^>]+)></)
         {
            print XMLIDX "      <indexitem text=\"$text\"";

            if ($target)
            {
               print XMLIDX " target=\"$target\">\n";
            }
            else
            {
               print XMLIDX " expand=\"false\">\n";
            }
         }
         else
         {
            print XMLIDX "      <indexitem text=\"$text\"";

            if ($target)
            {
               print XMLIDX " target=\"$target\"/>\n";
            }
            else
            {
               print XMLIDX "/>\n";
            }
         }
      }
      elsif ($sorted[$i]=~m/^<(.+)>##(.+)?$/)
      {
         my $target= $2;
         my $text = $1;

         if ($i > 0 and $sorted[$i-1]=~m/^<[^>]+><[^>]+><[^>]+>##/)
         {
            print XMLIDX "      </indexitem>\n";
            print XMLIDX "   </indexitem>\n";
         }
         elsif ($i > 0 and $sorted[$i-1]=~m/^<[^>]+><[^>]+>##/)
         {
            print XMLIDX "   </indexitem>\n";
         }

         if ($i < $#sorted and $sorted[$i+1]=~m/^<([^>]*)></)
         {
            print XMLIDX "   <indexitem text=\"$text\"";

            if ($target)
            {
               print XMLIDX " target=\"$target\">\n";
            }
            else
            {
               print XMLIDX " expand=\"false\">\n";
            }
         }
         else
         {
            print XMLIDX "   <indexitem text=\"$text\"";

            if ($target)
            {
               print XMLIDX " target=\"$target\"/>\n";
            }
            else
            {
               print XMLIDX "/>\n";
            }
         }
      }
   }

   if ($sorted[$#sorted]=~m/^<[^>]+><[^>]></)
   {
      print XMLIDX "      </indexitem>\n";
      print XMLIDX "   </indexitem>\n";
   }
   elsif ($sorted[$#sorted]=~m/^<[^>]+></)
   {
      print XMLIDX "   </indexitem>\n";
   }

   print XMLIDX "</index>\n";

   close XMLIDX;
}

sub do_helpset{
   open HELPSET, ">$destdir$dd$basename.hs"
      or die "Can't open '$destdir$dd$basename.hs': $!";

   print HELPSET "<?xml version='1.0' encoding='ISO-8859-1' ?>\n";
   print HELPSET "   <!DOCTYPE helpset\n";
   print HELPSET "     PUBLIC  \"-//Sun Microsystems Inc.//DTD JavaHelp HelpSet Version 2.0//EN\"\n";
   print HELPSET "     \"http://java.sun.com/products/javahelp/helpset_2_0.dtd\">\n\n";
   print HELPSET "<helpset version=\"2.0\">\n";
   print HELPSET "   <!-- title -->\n";
   print HELPSET "   <title>$title</title>\n";

   print HELPSET "   <!-- maps -->\n";
   print HELPSET "   <maps>\n";
   print HELPSET "   <homeID>top </homeID>\n";
   print HELPSET "   <mapref location=\"Map.jhm\" />\n";
   print HELPSET "   </maps>\n";

   print HELPSET "   <!-- views -->\n";
   print HELPSET "   <view xml:lang=\"$lang\" mergetype=\"javax.help.UniteAppendMerge\">\n";
   print HELPSET "      <name>TOC</name>\n";
   print HELPSET "      <label>Table Of Contents</label>\n";
   print HELPSET "      <type>javax.help.TOCView</type>\n";
   print HELPSET "      <data>${basename}TOC.xml</data>\n";
   print HELPSET "   </view>\n";

   print HELPSET "   <view xml:lang=\"$lang\" mergetype=\"javax.help.SortMerge\">\n";
   print HELPSET "      <name>Index</name>\n";
   print HELPSET "      <label>Index</label>\n";
   print HELPSET "      <type>javax.help.IndexView</type>\n";
   print HELPSET "      <data>${basename}Index.xml</data>\n";
   print HELPSET "   </view>\n";

   print HELPSET "   <view xml:lang=\"$lang\">\n";
   print HELPSET "      <name>Search</name>\n";
   print HELPSET "      <label>Search</label>\n";
   print HELPSET "      <type>javax.help.SearchView</type>\n";
   print HELPSET "         <data engine=\"com.sun.java.help.search.DefaultSearchEngine\">\n";
   print HELPSET "         JavaHelpSearch\n";
   print HELPSET "         </data>\n";
   print HELPSET "   </view>\n";

   print HELPSET "   <!-- presentation windows -->\n";
   print HELPSET "   <!-- main window -->\n";
   print HELPSET "   <presentation default=true>\n";
   print HELPSET "      <name>main window</name>\n";
   print HELPSET "      <size width=\"600\" height=\"600\" />\n";
   print HELPSET "      <location x=\"200\" y=\"200\" />\n";
   print HELPSET "      <title>$title</title>\n";
   print HELPSET "      <toolbar>\n";
   print HELPSET "         <helpaction image=\"backIcon\">javax.help.BackAction</helpaction>\n";
   print HELPSET "         <helpaction image=\"forwardIcon\">javax.help.ForwardAction</helpaction>\n";
   print HELPSET "         <helpaction image=\"homeIcon\">javax.help.HomeAction</helpaction>\n";
   print HELPSET "      </toolbar>\n";

   print HELPSET "      <image>appIcon</image>\n";

   print HELPSET "   </presentation>\n";

   print HELPSET "   <!-- secondary window -->\n";
   print HELPSET "   <presentation displayviews=false>\n";
   print HELPSET "      <name>secondary window</name>\n";
   print HELPSET "      <size width=\"450\" height=\"500\" />\n";
   print HELPSET "      <location x=\"200\" y=\"200\" />\n";

   print HELPSET "      <image>appIcon</image>\n";

   print HELPSET "   </presentation>\n";

   print HELPSET "   <!-- implementation section -->\n";
   print HELPSET "   <impl>\n";
   print HELPSET "      <helpsetregistry helpbrokerclass=\"javax.help.DefaultHelpBroker\" />\n";
   print HELPSET "      <viewerregistry viewertype=\"text/html\"\n";
   print HELPSET "         viewerclass=\"com.sun.java.help.impl.CustomKit\"/>\n";
   print HELPSET "      <viewerregistry viewertype=\"text/xml\"\n";
   print HELPSET "          viewerclass=\"com.sun.java.help.impl.CustomXMLKit\" />\n";
   print HELPSET "   </impl>\n";

   print HELPSET "</helpset>\n";
   close HELPSET;
}

sub do_map{

   open MAP, ">$destdir${dd}Map.jhm"
      or die "Can't open '$destdir${dd}Map.jhm': $!";

   print MAP "<?xml version='1.0' encoding='ISO-8859-1' ?>\n";
   print MAP "   <!DOCTYPE map\n";
   print MAP "     PUBLIC \"-//Sun Microsystems Inc.//DTD JavaHelp Map Version 2.0//EN\"\n";
   print MAP "     \"http://java.sun.com/products/javahelp/map_2_0.dtd\">\n\n";

   print MAP "<map version=\"2.0\" xml:lang=\"$lang\">\n";
   print MAP "<mapID target=\"top\" url=\"index.html\" />\n";
   print MAP "<mapID target=\"appIcon\" url=\"../../sharedimages/logosmall.png\" />\n";
   print MAP "<mapID target=\"homeIcon\" url=\"../../sharedimages/home.png\" />\n";
   print MAP "<mapID target=\"backIcon\" url=\"../../sharedimages/back.png\" />\n";
   print MAP "<mapID target=\"forwardIcon\" url=\"../../sharedimages/forward.png\" />\n";

   print MAP "<mapID target=\"popup_icon\" url=\"../../sharedimages/popup.png\" />\n";
   print MAP "<mapID target=\"images.popup\" url=\"../../sharedimages/popup.png\" />\n";

   foreach my $key (keys %map)
   {
      print MAP "<mapID target=\"$key\" url=\"$map{$key}\" />\n";
   }

   print MAP "</map>\n";
   close MAP;
}

sub do_toc{
   my ($htmltoc)=@_;

   open TOC, ">$destdir$dd${basename}TOC.xml"
      or die "Can't open '$destdir$dd${basename}TOC.xml': $!";

   print TOC "<?xml version='1.0' encoding='ISO-8859-1' ?>\n";
   print TOC "   <!DOCTYPE toc\n";
   print TOC "     PUBLIC \"-//Sun Microsystems Inc.//DTD JavaHelp TOC Version 2.0//EN\"\n";
   print TOC "     \"http://java.sun.com/products/javahelp/toc_2_0.dtd\">\n\n";

   print TOC "<toc version=\"2.0\" xml:lang=\"$lang\">\n";

   open HTMLTOC, $htmltoc or die "Can't open '$htmltoc': $!";

   # This assumes LaTeX2HTML has created the table of contents file
   while (<HTMLTOC>)
   {
      last if (m/<!--Table of Contents-->/i);
   }

   my $tocinfo = "";

   while (<HTMLTOC>)
   {
      last if (m/<!--End of Table of Contents-->/);

      $tocinfo .= " ".$_;
   }

   $tocinfo=~s/^\s*<UL>(.*)<\/UL>\s*$/$1/is;

   print TOC "<tocitem text=\"$title\" target=\"top\">\n";
   print TOC &getxmltoc($tocinfo);
   print TOC "</tocitem>\n";

   close HTMLTOC;

   print TOC "</toc>\n";
   close TOC;
}

sub getxmltoc{
   my($tocinfo)=@_;
   my($xmltoc)='';

   while ($tocinfo=~m/<LI>/is)
   {
      $tocinfo = $';

      if ($tocinfo=~s/^<A NAME="([^"]+)"\s*HREF="([^"]+)\.(html?)">(.*?)<\/A>//is)
      {
         my $target = $2;
         $map{$2}= "$target.$3";
         my $text   = $4;

         if ($tocinfo=~m/^\s*<LI>/is)
         {
            # this item followed by an item on the same level
            $xmltoc .= "<tocitem text=\"$text\" target=\"$target\"/>\n";
         }
         elsif ($tocinfo=~s/^\s*<\/UL>\s*<\/UL>//is)
         {
            # last item of group on this level goes back up two levels
            $xmltoc .= "<tocitem text=\"$text\" target=\"$target\"/>\n";
            $xmltoc .= "</tocitem>\n";
            $xmltoc .= "</tocitem>\n";
         }
         elsif ($tocinfo=~s/^\s*<\/UL>//is)
         {
            # last item of group on this level goes back up one level
            $xmltoc .= "<tocitem text=\"$text\" target=\"$target\"/>\n";
            $xmltoc .= "</tocitem>\n";
         }
         elsif ($tocinfo=~s/^\s*<UL>//is)
         {
            # item followed by lower level
            $xmltoc .= "<tocitem text=\"$text\" target=\"$target\">\n";
         }
         else
         {
            # last item
            $xmltoc .= "<tocitem text=\"$text\" target=\"$target\"/>\n";
         }
      }
   }

   $xmltoc;
}

1;
