#!/usr/bin/perl -w

#  dumblate.pl -- Template system for the weak
#
#  dumblate is a small (and dumb) script to manage a set of text files
#  and turn them into more readable HTML, or any other format for
#  instance, using perl's Template system.
#
#  Yes it's dumb. Hence the name. But I wanted to have a look at perl's
#  Template, and BTW I needed some tiny blosxom-like templating system I
#  could hack quickly.
#
#  Usage: have a look at the code.
#  Author: oz <oz@tuxaco.net>

use strict;
use warnings;
use File::Find;
use Template;

# Title
my $title = '/var/log/oz';

# Where are text files kept ?
my $text_path = '/where/the/sun/shines/';
my $extension = 'txt';

# Where do we generate pages
my $data_path  = '/path/to/the/dark/side';
my $data_ext   = 'html';

# Templates anyone ?
my $template_path = $text_path;

# ----------------------------------------------------------------------------

# If first arg exists, and is true in a perlish way, we should rebuild
# the whole archive.
my $rebuild_all = shift || 0;
umask 022;
my %entries;

print "* Welcome to dumblate!\n\n";
# Find text files
find( { wanted => sub {
        my $file = $_;
        return unless (-f $file)
            && ($File::Find::dir eq $text_path)
            && ($file =~ /\.$extension$/);

        my $staticname = $file;
        $staticname =~ s/^(.*)\.$extension$/$1\.$data_ext/g;
        $staticname =~ s/^$text_path/$data_path/g;
        $entries{$file} = { dest => $staticname };
    }, no_chdir => 1 }, $text_path );

# Build entries
foreach my $file (sort keys %entries) {
    my $item_title = undef;

    if ($rebuild_all || ! -f $entries{$file}->{'dest'}) {
        $entries{$file}->{'title'} = build($file, $entries{$file}->{'dest'});
    } else {
        $entries{$file}->{'title'} = grab_title($file);
    }

    # Make Relative URL
    $entries{$file}->{'url'} = $entries{$file}->{'dest'};
    $entries{$file}->{'url'} =~ s/$data_path\///g;

    # Plus short name
    $entries{$file}->{'num'} = $entries{$file}->{'url'};
    $entries{$file}->{'num'} =~ s/\.html//g;

    # Oh, and mtime too ?
    $entries{$file}->{'date'} = scalar localtime( (stat($file))[9] );

}

# Build index
template('index', \%entries);

# ----------------------------------------------------------------------------

# Build one entry
sub build {
    my ($source, $dest) = @_;
    my $item_title;
    my $item_body;
    return 0 if (!defined $source || !defined $dest);

    open(SRC, $source) or return warn("Can't read $source.\n");
    $item_title = <SRC>;
    chomp $item_title;
    {
        local $/ = undef;
        $item_body = <SRC>;
    }
    chomp $item_body;
    close(SRC);

    template('entry', $item_title, $item_body, $dest);
    return $item_title;
}

# Grab first line of file, which incidently is its designated title.
sub grab_title {
    my ($source) = @_;
    return undef unless defined $source;

    open(SRC, $source) or return warn("Can't read $source.\n");
    my $title = <SRC>;
    close(SRC);
    chomp $title;
    return $title;
}

# Template things
sub template {
    my $type = shift;
    my $vars;
    my $output;
    my $item_title;
    my $item_data;

    # Building one entry
    if ('entry' eq $type) {
        ($item_title, $item_data, $output) = @_;
        $vars = {
            title => $item_title,
            body  => $item_data,
        };
        print "Generating: $output ($item_title)\n";
    }

    # Building entry list (index.html)
    if ('index' eq $type) {
        $item_data = shift;
        $output    = "$data_path/$type.$data_ext";
        $vars      = {
            entries => [],
            title   => $title,
        };
        foreach my $k (keys %$item_data) {
            push @{$vars->{'entries'}}, $item_data->{$k};
        }
        print "Generating: $type.$data_ext\n";
    }

    # Writing template
    open(my $out, ">$output") or
        return warn("Can't write $output.\n");
    my $tt = Template->new( ABSOLUTE => 1 );
    $tt->process("$template_path/$type.tpl", $vars, $out)
        or warn("Failed : " . $tt->error() . "\n");
    close($out);
}