#!/usr/bin/perl -w
#
# htmlizer.pl 
# 
# J. Uckelman (uckelman@iastate.edu)
# 24 September 2000
#
my $start = time;

require 5.005;
use DBI;

my $version = 0.1;
my $config = '/home/g1/bin/scripts.conf';

use Getopt::Long;
Getopt::Long::Configure("bundling");
%opctl = ("help" => \$help, "version" => \$ver);
GetOptions(\%opctl, "help", "version");

print <<HELP and exit 0 if $help;
Usage:  htmlizer.pl [--help|--version]
        htmlizer.pl target...

        --help          prints this help
        --version       prints program version
HELP

print "htmlizer.pl $version\n" and exit(0) if $ver;

# load the config file 
eval { require $config; }; die "$0: $config: $@\n" if $@;

$| = 1; # flush after each print, heightens the drama

# are there targets?
defined $ARGV[0] or die "$0: no target\n";

# connect to game database
$dbh = DBI->connect($dsn, $user, $password);

# iterate over target list
while ($ARGV[0]) {
	my $then = time; # then is now
	print "making $ARGV[0]: ";
	
	my $target = $ARGV[0];
	my $result = '';	

	if (defined($$target) && $$target eq 'numerical') {
		# set variables for target
		my $base = $target;
		$base =~ s/_/./g;
		my $title = ${"${target}_title"};
		my $perpage = ${"${target}_perpage"};
		my $lock = ${"${target}_lock"};
		my $page_query = ${"${target}_page_query"};
		my $body_query = ${"${target}_body_query"};
		my $hist_query = ${"${target}_hist_query"};
		my $record_fmt = ${"${target}_record_fmt"};
		my $table = ${"${target}_table"};
		my $links = ${"${target}_links"};
	
		# get templates
	        my $header = &opentpl("$base.html.header");
	        my ($link, $here) = split /\n/, &opentpl("$base.html.hlinks");
	        my $footer = &opentpl("$base.html.footer");

	        # prevent changes while we're working
		$lock =~ s/(,|$)/ write$1/g;
	        $dbh->do("lock tables $lock");
	        
		# make each page
		my @pages = &pages($page_query, $perpage);
		my $page;
		foreach $page (@pages) {
			# make page parts
			my $first = ($page - 1) * $perpage + 1;
			my $last = $page * $perpage;
			my $head = &header($header, $title, $page, $perpage, $first, $last);
			my $hlinks = ($links) ? &hlinks($page, $perpage, $here, $link, @pages) : '';
			my $body = &body($body_query, 1, $hist_query, $table, $record_fmt, $first, $last);
			$body = &replace($body, "$base.html.replace");
			my $foot = &footer($footer);
		
			# write output
		        open OUT, ">$WWW/$base.$page.html" or die "$0: $base.$page.html: $!\n";
			print OUT "$head$hlinks$body$hlinks$foot";
			close OUT;
	
			print '.';
		}
		$result = 'ok';
	}
	elsif (defined($$target) && $$target eq 'single') {
		# set variables for target
		my $base = $target;
		$base =~ s/_/./g;
		my $title = ${"${target}_title"};
		my $lock = ${"${target}_lock"};
		my $body_query = ${"${target}_body_query"};
		my $hist_query = ${"${target}_hist_query"};
		my $record_fmt = ${"${target}_record_fmt"};
		my $table = ${"${target}_table"};
	
		# get templates
	        my $header = &opentpl("$base.html.header");
	        my $footer = &opentpl("$base.html.footer");

	        # prevent changes while we're working
		$lock =~ s/(,|$)/ write$1/g;
	        $dbh->do("lock tables $lock");
	        
		# make page parts
		my $head = &header($header, $title, 0, 0, 0, 0);
		my $body = &body($body_query, $hist_query eq '' ? 0 : 1, $hist_query, $table, $record_fmt, 0, 0);
		$body = &replace($body, "$base.html.replace");
		my $foot = &footer($footer);
		
		# write output
		open OUT, ">$WWW/$base.html" or die "$0: $base.html: $!\n";
		print OUT "$head$body$foot";
		close OUT;

		print '.';
		$result = 'ok';
	}
	elsif ($target eq 'all') {	
		shift @ARGV;
		unshift @ARGV, 'skip me', @ALL;
		$result = $#ARGV;
	}
	elsif ($target eq 'clean') {
		`rm -f $TMP/*`;
		$result =  'ok';
	}
	else { die "\n\tunrecognized target: $ARGV[0]\n"; }

	print ".done, ", time - $then, "s\033[60G[ $result ]" unless $target eq 'all';
	print "\n";
	shift @ARGV;
}

$dbh->disconnect;

print "done, ", time - $start, "s\n";
exit 0;

#
# opentpl
#
sub opentpl ($) {
	my ($file) = @_;
	open FILE, "<$TPL/$file"  or die "$0: $file: $!\n";
	my $data = join '', <FILE>;
	close FILE;
	return $data;
}

#
# replace
#
sub replace ($$) {
	my ($data, $pairfile) = @_;
	my @fr = split /\n/, &opentpl($pairfile);
	my (@find, @replace);
	for (my $i = 0; $i <= ($#fr / 2); $i++) {
		$find[$i] = @fr[$i * 2];
		$replace[$i] = @fr[$i * 2 + 1];
	}

	for (my $i = 0; $i <= $#find; $i++) {
		eval "\$data =~ s/$find[$i]/sprintf(\"$replace[$i]\")/gesx";
        }

	return $data; 
}

#
# guard
#
sub guard ($) {
	my ($str) = @_;
	$str =~ s/(["@])/\\$1/g; # guard @'s and "'s
	$str =~ s/%/%%/g; # guard %'s from sprintf
	return $str;
}

#
# unguard
#
sub unguard ($) { 
	my ($str) = @_;
	$str =~ s/\\\"/\"/g; # unguard "'s
	return $str;
}

#
# hlinks
#
sub hlinks ($$$$@) {
	my ($curpage, $perpage, $here, $link, @pages) = @_;
	my ($tmp, $linkpage);
	my $output = '';

	foreach $page (@pages) {
		my $range = (($page - 1) * $perpage + 1) . '-' . ($page * $perpage);
		$linkpage = $page;
		$tmp = ($page == $curpage) ? $here : $link;
		
		# interpolate
		$tmp = &guard($tmp);
		eval "\$tmp = sprintf(\"$tmp\")";
		$output = $output . &unguard($tmp);
	}

	return "<center>" . $output . "</center>\n<hr>";
}

#
# getmaxrev
#
sub getmaxrev ($$) {
	my ($table, $number) = @_;

	# get max revision number
        my $sth = $dbh->prepare("select max(revision) from $table where number = $number");
        $sth->execute;
        my ($maxrev) = $sth->fetchrow_array;
        $sth->finish;

	return $maxrev;
}

#
# history
#
sub history ($) {
	my ($query) = @_;
	my ($tmp, $hrev, $date, $event);
	my $output = '';

	my $sth = $dbh->prepare($query);
	$sth->execute;
	for (($hrev, $event, $date) = $sth->fetchrow_array; defined($hrev); ($hrev, $event, $date) = $sth->fetchrow_array) { $output = $output . "\n$hrev. $event, $date"; }
	$sth->finish;
	$output =~ s/^\n//;

	return $output;
}

#
# header
#
sub header ($$$$$) {
	my ($header, $title, $page, $perpage, $first, $last) = @_;                
	my $range = "$first-$last";
	my $tmp = &guard($header);
        eval "\$tmp = sprintf(\"$tmp\")";
        return &unguard($tmp);
}

#
# footer
#
sub footer ($) {
	my ($footer) = @_;

	my $date = `date -u '+%a %d %b %Y %T %Z'`;
	my $tmp = &guard($footer);
	eval "\$tmp = sprintf(\"$tmp\")";
	return &unguard($tmp);
}

#
# body
#
sub body ($$$$$$@) {
	my ($body_query, $hist, $hist_query, $table, $record_fmt, $first, $last) = @_;
	my ($tmp, @tmp);
	my $body = '';

	eval "\$tmp = sprintf(\"$body_query\")";
	my $sth = $dbh->prepare($tmp);
	$sth->execute;

	# get column names
	my @element = @{$sth->{NAME}};

	# get each rule
	for (@tmp = $sth->fetchrow_array; defined($tmp[0]); @tmp = $sth->fetchrow_array) {
		# use refs to put data into vars named in @element
		for (my $i = 0; $i <= $#tmp; $i++) { ${$element[$i]} = $tmp[$i]; }
	
		# make history only if requested and for max revision number
		my $history = '';
		if ($hist && $revision == &getmaxrev($table, $number)) {
			eval "\$tmp = sprintf(\"$hist_query\")";
			$history = &history($tmp);
		}

		# interpolate values into record format
		eval "\$body = \$body . $record_fmt";
	}
	
	$sth->finish;

	return $body;
}

#
# pages
#
sub pages ($$) {
	my ($page_query, $perpage) = @_;

	my ($tmp, @pages);
        my @tmp = ();
        my $curmaxpage = 0;
	my $sth = $dbh->prepare($page_query);
        $sth->execute;
	while ($tmp = $sth->fetchrow_array) { push @tmp, $tmp; }
        $sth->finish;
	
        # add a new page to the list if record is not on current page
	foreach (@tmp) { push @pages, $curmaxpage = int(($_ - 1) / $perpage) + 1 if ($_ > $curmaxpage * $perpage); }

	return @pages;
}

#
# Motions_Archive
#
sub Motions_Archive {
#	my $base = 'Motions.Archive';
#	my $table = 'motion';
#	my $perpage = 50;
#	my $query = "select * from $table where number between \$first and \$last order by number, revision";
#	&numerical($base, $table, $perpage, $query);
#	&version($base);
#	return 'ok';
	return 'foo';
}

#
# Motions_Live
#
sub Motions_Live {
#	my $base = 'Motions.Live';
#	my $table = 'motion';
#	my $perpage = 'all';
#	my $query = "select * from $table where vitality = 'l' order by number";
#	my $page = &numerical($base, $table, $perpage, $query);
#	`mv -f $WWW/$base.$page.html $WWW/$base.html`;
#	return 'ok';
	return 'foo';
}
