#!/usr/bin/perl -w

#-----------------------------------------------------------
#
# SIMPLESITE
# 
# Copyright (C) 1999, 2000 by Arjan Scherpenisse <acscherp@wins.uva.nl>
#
# 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
#-----------------------------------------------------------

use strict;

my $BUILD_PROGRAM = "sisi-buildpage";
my $TAR_PATH = "/bin/tar";
my $CP_PATH = "/bin/cp";
my $extension;

my $vcount = 0;
my $configfile = "./configuration";
my ($help, $version, $verbose);

$| = 1;

#-- read_key_values ----------------------------------------
# this sub reads a file (first and only parameter) and returns an assiociative
# array with key-value pairs.
# key value pairs can be multi-lined if they are enclosed in <--  --> tags. 
# lines started with # are ignored.
sub read_key_values {

  # declare the local variables
  my($complexline, %dict, $file, $chunk, $ckey);

  # get first parameter
  ($file) = $_[0];

  # initialization
  $complexline = 0;
  $chunk="";
  $ckey = "";

  # open file
  open(FILE, $file) || die "No such file: $file";

 Loop:
  while (<FILE>)  {
    # read a line from the file

    next Loop if (/^[\s]*\#/) ;      # comment encountered. skip it.

    next Loop if (!$complexline && /^[\s]*$/); # empty line. skip it.

    if (/<--/) {		# multiline start
      $complexline = 1;
    } 

    if (!$complexline) {
      # if not, check the integrity of the line format
      if ($_ !~ /.*:[ ]*/) 
	{ $verbose && warn "Wrong line format in $file";
	} else {

	  # this statement puts the key-value pair of a simple formatted item into the dict.
	  # check this routine out .... god i love perl :)
	  /(.+):[ ]*(.*)/;
	  $dict{$1}=$2;
	}
    } else {
      # handle a complex line
      if ( /(.*)-->/ ) {
	# end of complex line reached.
	# ...add last part to line
	$chunk .= $1;
	# ...clean line of garbage
	$chunk =~ s/[\r\t\n ]+/ /g;
	# remove trailing whitespace
	$chunk =~ s/^[\s]//;
	# reset the flag
	$complexline = 0;
	# ...add it to the dict
	$dict{$ckey} = $chunk;

      } elsif ( /([\w]+):.*<--[\s]*(.*)/ ) {
	$complexline = 1;
	$chunk = $2 . " ";
	$ckey = $1;
	
      } else {
	# in a multiline, just add it
	$chunk .= $_;
      }
	
     } 
  }
  ($complexline) ? die "Unclosed multiline encountered in $file" : return %dict;
}
#-- merge_dicts --------------------------------------------------
# this subroutine takes two dictionaries as arguments and returns the 'merge'
# of these two dicts as one dictionary.  If duplicate keys are encountered, the value from the
# first dict is taken as new value.
sub merge_dicts {
  my ($dict1, $dict2, %newdict, $key);
  ($dict1, $dict2) = @_;
  foreach $key (keys %$dict2) {
    $newdict{$key} = $$dict2{$key};
  }
  foreach $key (keys %$dict1) {
    $newdict{$key} = $$dict1{$key};
  }
  return %newdict;
}

# prints version
sub version {
  print "SimpleSite 0.60 builder\n(c) 2000 Arjan Scherpenisse <acscherp\@wins.uva.nl>\nReleased under the GNU General Public License\nSee the file COPYING for more details\n\n";
}

# prints usage
sub usage {
  &version;
  print "usage: $0 \n";
  print "\t--file <configfile>\n";
  print "\t--debug\n";
  print "\t--help\n";
  print "\nOptions can be abreviated.\n"
}

sub verbose {
  my ($arg) = @_;
  $verbose && printf("%2d: %s\n", ++$vcount, $arg);
}

sub verify_config {
  my ($config) = @_;
  my @reqs = ("pages", "outputdir");
  my @reccs = ("themes","locales");
  my $halt = 0;

  foreach (@reqs) {
    if (!$$config{$_}) { 
      $halt=1; 
      print STDERR "> Required config item not found: $_\n"; 
    }
  }
  foreach (@reccs) {
    if (!$$config{$_}) { 
      print STDERR "> Using default value for: $_\n"; 
    }
  }

  $halt && die;
}

sub copy_extra_files {
  my ($theme, $outdir) = @_;
  my @files;
  if (-f "themes/$theme/extra_files") {
    $verbose && print "    ... copying extra files.";
    open (FILE, "<themes/$theme/extra_files");
    while (<FILE>) {
      foreach(split /[\s]+/) {
	system("$CP_PATH -r themes/$theme/$_ $outdir");
	$verbose && print ".";
      }
    }
    $verbose && print "done.\n";
  } else {
    verbose("No extra files for theme $theme.");
  }
}

sub main {
  my (%config, %conf, @themes, @locales, @pages, $outputdir,
     $theme, $page, $locale, $curfile);

  use Getopt::Long;

  &GetOptions("version" => \$version, 
	      "file=s"=>\$configfile, 
	      "debug"=>\$verbose,
	      "help"=>\$help);

  if ($version) { 
    &version; 
    exit 0;
  } 
  if ($help) {
    &usage;
    exit 0;
  }

  $verbose && &version;

  # fill in the defaults
  %config = ("locales", "C", "themes", "default", "extension", "html");

  # check if config file exists
  if (!-f $configfile) {
    print "File not found: $configfile\nexiting...\n";
    exit 1;
  }

  # read the config file and merge with defaults
  %conf = read_key_values($configfile);
  verify_config(\%conf);
  %config = merge_dicts(\%conf, \%config);

  
  umask 0022;

  # assign the required variables
  $outputdir = $config{"outputdir"};
  @themes = split (/\s+/, $config{"themes"});
  @locales = split (/\s+/, $config{"locales"});
  @pages = split (/\s+/, $config{"pages"});

  # and fill in the optional config-file specified values.
  # reasonable defaults are already filled in.
  $TAR_PATH = $config{"TAR_PATH"} if ($config{"TAR_PATH"});
  $CP_PATH = $config{"CP_PATH"} if ($config{"CP_PATH"});
  $BUILD_PROGRAM = $config{"BUILD_PROGRAM"} if ($config{"BUILD_PROGRAM"});
  $extension = $config{"extension"};

  # if the outputdir doesnt exist, create it.
  if (! -d $outputdir) {
    mkdir ($outputdir, 0755);
    verbose("Creating dir: $outputdir");
  }
  
  foreach $locale (@locales) {
    verbose("Locale building: $locale");
    mkdir ("$outputdir/$locale", 0755);
    foreach $theme (@themes) {
      
      # check if this theme exists
      if (-d "themes/$theme") {
	mkdir ("$outputdir/$locale/$theme", 0755);
	$verbose && print "    ... theme [$theme]:";
	foreach $page (@pages) {
	  $verbose && print " $page";
	  
	  $curfile = "$outputdir/$locale/$theme/$page.$extension";
	  system("$BUILD_PROGRAM --theme $theme --page $page --locale $locale > $curfile");
	}
	$verbose && print ".\n";
	&copy_extra_files($theme, "$outputdir/$locale/$theme");
      } else {
	warn "No such theme: $theme";
      }
    }
  }
}

&main;
