#! /usr/bin/perl -w

use DocFilter;
use DocUtils;
use FileList;
use SourceFile;
use DirHandle;
use BerkeleyDB;
use strict;

DocUtils->evalConfigFile("doc.config");
DocUtils->clearLog();
DocUtils->clearErrorLog();

my $checkTimeStamp = 1;
if (($ARGV[0]) && ($ARGV[0] eq "all")) {
    $checkTimeStamp = undef;
}

convertSourceFiles(".");
processDirectory(".", $checkTimeStamp);


if (-e "index.html") {
    DocUtils->copy("index.html", ".", $ENV{HTML_DIR});
}
if (-e "cxxblas.html") {
    DocUtils->copy("cxxblas.html", ".", $ENV{HTML_DIR});
}
if (-e "frontpage.css") {
    DocUtils->copy("frontpage.css", ".", $ENV{HTML_DIR});
}

if (-e "default.css") {
    DocUtils->copy("default.css", ".", $ENV{HTML_DIR});
}


### create file list

#   {
#       my $filelist = FileList->new(".");
#   
#       my @outBuffer;
#       push(@outBuffer, DocUtils->loadLinebuffer($ENV{SLIDE_HEADER}));
#       push(@outBuffer, $filelist->linebuffer("flens/blas/level1"));
#       push(@outBuffer, DocUtils->loadLinebuffer($ENV{SLIDE_FOOTER}));
#   
#       my $htmlfile = join("/", $ENV{HTML_DIR}, "flens.blas.level1.files.html");
#       $ENV{REL_HTML_DIR} = ".";
#       @outBuffer = DocUtils->expandShellVariables(@outBuffer);
#       DocUtils->saveLinebuffer($htmlfile, @outBuffer);
#   }

if (($ARGV[0]) && ($ARGV[0] eq "files")) {
    $ENV{FILE_TREE} = undef;
    $ENV{PREVIOUS_PAGE} = undef;
    $ENV{NEXT_PAGE} = undef;
    $ENV{CURRENT_FILENAME} = undef;
    $ENV{NAV_UP} = "index.html";
    $ENV{NAV_UP_TOPIC} = "MAIN";
        
    my $filelist = FileList->new(".");
    my @subdirs = $filelist->subdirs();
    foreach my $dir (sort @subdirs) {
        my @outBuffer;
        push(@outBuffer, DocUtils->loadLinebuffer($ENV{SLIDE_HEADER}));
        push(@outBuffer, $filelist->linebuffer($dir));
        push(@outBuffer, DocUtils->loadLinebuffer($ENV{SLIDE_FOOTER}));
        
        $dir =~ s/\//./g;
        $dir = $dir . ".files.html";
        if ($dir =~ /^cxxblas/) {
            $ENV{NAV_UP} = "cxxblas.html";
            $ENV{NAV_UP_TOPIC} = "CXXBLAS";
        } else {
            $ENV{NAV_UP} = "index.html";
            $ENV{NAV_UP_TOPIC} = "FLENS";
        }
        
        
        my $htmlfile = join("/", $ENV{HTML_DIR}, "$dir");
        $ENV{REL_HTML_DIR} = ".";
        @outBuffer = DocUtils->expandShellVariables(@outBuffer);
        DocUtils->saveLinebuffer($htmlfile, @outBuffer);
        print "generated $htmlfile\n";
    }
}

sub processDirectory
{
    my ($path, $checkTimeStamp) = @_;


    my $fullpath = join("/", $ENV{DOCSRC_DIR}, $path);
    my $dh = DirHandle->new($fullpath) || die ("cannot open dir: $path");
    my @itemlist;
    my $lastPage = 0;
    while (my $item = $dh->read()) {
        next if (($item eq ".") || ($item eq ".."));
        push(@itemlist, $item);
        if ($item =~ /page(\d\d).doc/) {
            $lastPage = ($1>$lastPage) ? $1 : $lastPage;
        }
    }

    # process subdirs
    foreach my $item (@itemlist) {
        if (-d join("/", $fullpath, $item)) {
            processDirectory(join("/", $path, $item), $checkTimeStamp);
        }
    }
    
    #process files in current dir
    foreach my $item (@itemlist) {
        if ($item =~ /\.doc$/) {
            my ($nav_up, $nav_up_topic) = navUp($path);

            if ($item eq "index.doc") {
                $ENV{NAV_UP} = undef;
                $ENV{NAV_UP_TOPIC} = undef;
                $ENV{LAST_PAGE} = undef;
                $ENV{FILE_TREE} = undef;
            } else {
                $ENV{NAV_UP} = $nav_up;
                $ENV{NAV_UP_TOPIC} = $nav_up_topic;
                $ENV{LAST_PAGE} = ($lastPage>0) ? $lastPage : undef;
            }
            processFile($path, $item, $checkTimeStamp);
        }
    }
}

sub processFile
{
    my ($path, $filename, $checkTimeStamp) = @_;

    $path =~ s/^\.\///;
    print STDERR "processing $path/$filename ...";

    my $fullpath = join("/", $ENV{DOCSRC_DIR}, $path);

    $filename =~ /(.*)\.doc$/;
    my $htmlfile = join("/", $ENV{HTML_DIR}, $path, "${1}.html");
    
    my $srcTime = (stat "$fullpath/$filename")[9];
    my $outTime = (stat "$htmlfile")[9];

    if ((defined $outTime) && ($srcTime < $outTime) && ($checkTimeStamp)) {
        print STDERR " is up to date\n";
        return;
    }

    my $entry = "Processing docfile $path/$filename";
    DocUtils->addToLog("\n" . "=" x length($entry) . "\n");
    DocUtils->addToLog("$entry\n");
    DocUtils->addToLog("=" x length($entry) . "\n");
    


    $ENV{TOPIC} = "";
    $ENV{CURRENT_PATH} = $path;
    $ENV{CURRENT_FILENAME} = $filename;
    ($ENV{REL_HTML_DIR} = $path) =~ s/[^\.\/][^\/]+/\.\./g;
    $ENV{RELPATH} = DocUtils->relativePath(join("/", $ENV{HTML_DIR}, $path));

    #TODO
    if ($filename =~ /page(\d*)\.doc/) {
        my $page = $1;
        my $prev = $page - 1;
        my $next = $page + 1;
        $ENV{PAGE} = $page;

        $ENV{PREVIOUS_PAGE_DOC} = "page". sprintf("%02d", $prev) . ".doc";
        $ENV{NEXT_PAGE_DOC} = "page". sprintf("%02d", $next) . ".doc";

        ($ENV{PREVIOUS_PAGE_HTML} =$ENV{PREVIOUS_PAGE_DOC}) =~ s/\.doc/.html/;
        ($ENV{NEXT_PAGE_HTML} = $ENV{NEXT_PAGE_DOC}) =~ s/\.doc/.html/;


        $ENV{PREVIOUS_PAGE} = (-e "$fullpath/$ENV{PREVIOUS_PAGE_DOC}") ? ($prev) : undef;
        $ENV{NEXT_PAGE} = (-e "$fullpath/$ENV{NEXT_PAGE_DOC}") ? $next : undef;
        $ENV{FILE_TREE} = undef;

        $ENV{FORMULA_COUNTER} = 1;
    } else {
        $ENV{PAGE} = $ENV{PREVIOUS_PAGE} = $ENV{NEXT_PAGE} = undef;
        my $linkToFileTree = $ENV{RELPATH};
        $linkToFileTree =~ s/([^.])\//$1./g;
        $linkToFileTree = $linkToFileTree . ".files.html";
        
        unless ($filename eq "index.doc") {
            $ENV{FILE_TREE} = $linkToFileTree;
        }
print "\nFILE_TREE = $ENV{FILE_TREE}\n";
        $ENV{FORMULA_COUNTER} = $ENV{RELPATH} = undef;
    }

    my $fh = FileHandle->new("< $fullpath/$filename") || die ("cannot open $fullpath/$filename\n");

    my @outBuffer;
    my $filter = DocFilter->new($fh);
    $ENV{TOPIC} = join(" - ", split("/", $path), $filter->{TITLE});
    push(@outBuffer, DocUtils->loadLinebuffer($ENV{SLIDE_HEADER}));
    push(@outBuffer, $filter->linebuffer);
    push(@outBuffer, DocUtils->loadLinebuffer($ENV{SLIDE_FOOTER}));
    @outBuffer = DocUtils->expandShellVariables(@outBuffer);
    
    DocUtils->saveLinebuffer($htmlfile, @outBuffer);

    addToTOC($path, $filename, $filter);
    print STDERR "\n    generated $htmlfile\n";
}

sub addToTOC
{
    my ($path, $filename, $filter) = @_;

    my $tocpath = join("/", $ENV{TMP_DIR}, $path);
    my $tocfilename = "$tocpath/toc.db";
    
    DocUtils->mkdir($tocpath);
    
    tie my %TOC, "BerkeleyDB::Hash",
        -Filename => $tocfilename,
        -Flags    => DB_CREATE
    || die "can not tie to $tocpath";

    $TOC{$filename} = $filter->{TITLE};
    DocUtils->addToLog("addToTOC:\n    added entry \$TOC{$filename} = $filter->{TITLE}");
    DocUtils->addToLog(" to $tocfilename\n");
    untie %TOC;
}

sub navUp
{
    my $path = shift;
    my $fullpath = join("/", $ENV{DOCSRC_DIR}, $path);

    my ($nav_up, $nav_up_topic);
    my @path = split("/", $path);
    if ($#path == 0) {
        $nav_up_topic = "MAIN";
        $nav_up = "index.html";
        return ($nav_up, $nav_up_topic);
    }
    if ($#path == 1) {
        $nav_up_topic = "MAIN";
        $nav_up = "../index.html";
        return ($nav_up, $nav_up_topic);
    }
    
    my $count = -2;
    $nav_up = "";
    while (1) {
        $nav_up = $nav_up . "../";
        if (-e "$fullpath/$nav_up/index.doc") {
            $nav_up = $nav_up . "index.html";
            last;
        }
        
        if (-e "$fullpath/$nav_up/$path[$count].doc") {
            $nav_up = $nav_up . "$path[$count].html";
            last;
        }
        --$count;
    }
    $nav_up_topic = "Up: " . uc($path[$count]);
    return ($nav_up, $nav_up_topic);
}

sub convertSourceFiles
{
    my $path = shift;

    my $fullpath = join("/", $ENV{DOCSRC_DIR}, $path);
    my $dh = DirHandle->new($fullpath) || die ("cannot open dir: $path");
    my @itemlist;
    while (my $item = $dh->read()) {
        next if (($item eq ".") || ($item eq ".."));
        push(@itemlist, $item);
    }

    foreach my $item (@itemlist) {
        if (-d join("/", $fullpath, $item)) {
            convertSourceFiles(join("/", $path, $item));
        }
        if ($item =~ /\.doc$/) {
            DocUtils->copy($item, $path, $ENV{HTML_DIR} . "/$path", "$item.txt");
        }
        if ($item =~ /\.(h|tcc|cc)$/) {
            $path =~ s/^\.\///;
            $ENV{CURRENT_PATH} = $path;
            $ENV{CURRENT_FILENAME} = $item;
            ($ENV{REL_HTML_DIR} = $path) =~ s/[^\.\/][^\/]+/\.\./g;
            $ENV{RELPATH} = DocUtils->relativePath(join("/", $ENV{HTML_DIR}, $path));


            my $filename = join("/", $path, $item);
            my $htmlfile =  join("/", $ENV{HTML_DIR}, "${filename}.html");
            if (DocUtils->isNewerThan($filename, $htmlfile)) {

                my $linkToFileTree = $ENV{RELPATH};
                $linkToFileTree =~ s/([^.])\//$1./g;
                $linkToFileTree = $linkToFileTree . ".files.html";

                $ENV{NAV_UP} = $linkToFileTree;
                $ENV{NAV_UP_TOPIC} = "Browse Files";
                my @linebuffer;
                push(@linebuffer, DocUtils->loadLinebuffer($ENV{SLIDE_HEADER}));
                push(@linebuffer, DocUtils->convertCode($filename, "on", "on"));
                push(@linebuffer, DocUtils->loadLinebuffer($ENV{SLIDE_FOOTER}));
                @linebuffer = DocUtils->expandShellVariables(@linebuffer);
                DocUtils->addToLog("convertSourceFiles():\n    converted $filename -> $htmlfile\n");
                DocUtils->saveLinebuffer($htmlfile, @linebuffer);
                DocUtils->checkLinelength($filename, 80);
            }
        }
    }
}
