package CompoSite::Navgen;

# CompoSite, a Perl module to server web pages from BlockBin.
# This file contains some navigation-generation code.
# Copyright (C) 2001 Tom Rathborne
# Copyright (C) 2001 Convoke Communications Corp.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

# The CompoSite navigation generator -----------------------------------------

=pod

Traverse produces hash/array alternating tree like this:

{
    path        => ''
    tpart       => '',
    title       => 'Home Page',
    children    => [
        {
            path        => 'foo.html',
            tpart       => 'Foos',
            title       => 'Foos and Accessories'
            children    => [],
        },

        {
            path        => 'bar', # may actually be bar.html w/children
            tpart       => 'Bars',
            title       => 'Bars & Accessories',
            children    => [
                {
                    path        => 'baz',
                    tpart       => 'Baz Widgets',
                    title       => 'Baz Widgets',
                    children    => [],
                },
                
                {
                    path        => 'qux',
                    tpart       => 'Qux Widgets',
                    title       => 'Qux Widgets',
                    children    => [],
                },
            ],
        },
    ],
}

=cut

use CompoSite::Util;
use IO::File;

sub Traverse ($$$$) { # recursively build navigation
    my ($node, $builders, $root, $defaults) = @_;

    my $path = $node->{'path'};
    $node->{'children'} = [];

    my $file = $root.$path;

    my %argh = %{$defaults};
    my $args = \%argh; # pass defaults from config

    if (-d $file) {
        $path .= '/';
        $file .= '/index.html'; # we want to read this

        opendir (DIR, $root.$path) or die $!; # TODO - fail gracefully
        my @dentries = grep { $_ !~ /^\./ and $_ ne 'index.html' } readdir (DIR);
        closedir DIR;

        foreach my $dentry (sort @dentries) {
            push @{$node->{'children'}},
                    &Traverse ({path => $dentry}, $builders, $root.$path, $defaults);
        }
    }

    my $fh = new IO::File "<$file" or die $!; # TODO - fail gracefully

FH: while (my $line = <$fh>) {
        if ($line =~ /^--USE--\s*(.*)$/) {
            my $builder = $1;
            while (defined $builder and $builder ne '') {
                if (exists $builders->{$builder}) {
                    ($builder, $children) = &{$builders->{$builder}}($fh, $args);

                  # TODO - warn / don't allow synthentic children for dir/index.html
                    if (defined $children and ref $children eq 'ARRAY') {
                        $node->{'children'} = $children;
                        last FH; # TODO - is it ok that only first childbearing block counts?
                    }
                } else {
                    ($builder, $junk) = &CompoSite::Util::next_part($fh); # skip to next cut
                }
            }
        }
    }

    $fh->close;

    if (exists $node->{'children'} and scalar @{$node->{'children'}}) { # has kids
        $node->{'path'} =~ s/\.html$//; # make it look like a dir if it doesn't already
    }

    $node->{'children'} = [sort {$a->{'order'} <=> $b->{'order'}} @{$node->{'children'}}];

    $node->{'order'} = exists ($args->{'Order'}) ? $args->{'Order'} + 0 : 0;
    $node->{'title'} = $args->{'Title'};
    $node->{'tpart'} = $args->{'Tpart'};
    $node->{'tpart'} = $node->{'title'} unless defined $node->{'tpart'};

    return $node;
}

1;

# EOF ------------------------------------------------------------------------
