#################################################
# create_page.pl
# by Daniel Wedul (daniel@wedul.com)
# Created on: January 11, 2006
# Last Modified: January 26, 2006
#*********************
# This program requires the following perl programs to be in the same directory
#   <list dependencies here>
#*********************
# This program takes in a specially formatted template and some content files and outputs a standard html page
#*********************
#  Usage: create_page.pl <template file> <content file 1> [<content file 2> ...]
#	The template file and at least one content file must be provided.
#*********************
# template file tags:
#	<!--###CONTENT:nn###-->		nn is replaced by a two digit number
#		This tag causes one of the content files given at the command line to be inserted after this line
#		There must be one content file in the command line for every different nn.
#		The first given file will go in after the lowest nn value, the second after the second lowest etc.
#		Example:
#			Let's say a template has these two tags <!--###CONTENT:50###--> and <!--###CONTENT:32###-->
#			Calling this program to use that template must have 2 content files such as
#			create_page.pl template.txt content1.txt content2.txt
#			In this example, content1.txt will be placed directly after <!--###CONTENT:32###--> and
#			content2.txt will be placed directly after <!--###CONTENT:50###-->.
#	<!--###<filename>###-->		<filename> is replaced by a filename
#		The contents of <filename> will be placed after this tag
#		Example:
#			Let's say a template has the tag <!--###cats.txt###-->.
#			The contents of the file  cats.txt  will be placed directly after this tag.
#	<!--###<variable>###-->		<variable> is replaced by a variable name.
#		Sets a variable that must be defined in a content folder.  The value of the variable will be placed
#		directly after this tag.
#       <!--###DATE###-->	This will be replaced with the date that this program is run in the form of
#					month day, year (January 1, 2007 for example).
# content file tags:
#	<!--###SAVEAS=<filename>###-->		<filename> is replaced by a file name.
#		Tells this program what to save the resulting file as.
#		If no SAVEAS is defined, the output filename will be the same as the first content file but with the 
#			html extention.
#	<!--###<variable>=<filename>###-->	<variable> is replaced by a variable used in the template
#						<filename> is replaced by a file name.
#		Causes the contents of a filename to replace all matching variable tags in the template file
#	<!--###<variable>="value"###-->		value is replaced by something
#		Causes all matching variable tags to resolve to whatever is delimeted by the quotes (value).
# extra notes:
#	All <!--###<variable>###--> tags in the template must have a <!--###<variable>=xxx###--> tag in one of the main
#		content files
##################################################
use strict;
#<put the use lines here>

#################################################
############ Command Line Arguments #############
#################################################
#  Usage: create_page.pl <template file> <content file 1> [<content file 2> ...]

if ($#ARGV < 1) { die "ERROR: Not enough arguments given.\n".
		      "         At least one template and content file must be provided.\n".
		      "Usage: create_page.pl <template file> <content file 1> [<content file 2> ...]\n"; }

#pull in the command line arguments
my $TemplatePathFile = shift(@ARGV);
my @ContentFiles = @ARGV;

#################################################
##################### Setup #####################
#################################################

#find the path to the template and go there
my $PWD = `cd`;
my @PathToTemplate = split(/[\/\\]/, $TemplatePathFile);
my $TemplateFile = pop (@PathToTemplate);
my $Path = join ("\\", @PathToTemplate);
if ($Path eq "") { $Path = "."; }
chdir($Path);

print "    Path: $Path\n"."Template: $TemplateFile\n";
foreach (@ContentFiles) { print " Content: $_\n"; }


#make sure all these files exist
if (!(-e $TemplateFile)) { die "ERROR: The template file $TemplateFile does not exist.\n"; }
foreach my $file (@ContentFiles) { if (!(-e $file)) { die "ERROR: The content file $Path\\$file does not exist.\n"; } }

#read the template file
my @Template = split(/\n/, ReadFile($TemplateFile) );

#Get the content tags
my @tags = ();

#split the template up by newline character
foreach my $line ( @Template ) {
	#get rid of leading & trailingspaces
	chomp($line);
	$line =~ s/^[ \t]*//g;
	$line =~ s/$[ \t]*//g;
	#check if this line has a tag line
	if ($line =~ m/\<\!\-\-\#\#\#.*\#\#\#\-\-\>/) { 		
		#put it in the list of tags
		push @tags, $line;
		#get rid of the tag notifications to leave just the test.
		$tags[$#tags] =~ s/^\<\!\-\-\#\#\#//; 
		$tags[$#tags] =~ s/$\#\#\#\-\-\>//;
		$tags[$#tags] =~ s/[ \t]//g;
	}
}

#make sure the number of content tags matches the number of content files given
my $conttags = 0;
foreach my $tag (@tags) {
	if ($tag =~ /CONTENT:/) { $conttags += 1; }
}
my $contfiles = $#ContentFiles + 1;
if ($conttags != $contfiles) { die "ERROR: The template ".$TemplateFile." contains ".$conttags." CONTENT tags but ".
				   $contfiles." content files were provided.\n"; }

#create a hash to contain tags and their references
my %References = ();

#match content tags to content files by adding them to the hash when they find them.
foreach my $tag (@tags) {
	if ($tag =~ /^CONTENT:/) {
		foreach my $val (0..9) {
			my $lookfor = "CONTENT:0".$val;
			if ($tag eq $lookfor) { 
				$References{$lookfor} = shift (@ContentFiles);
			}
		}
		foreach my $val (10..99) {
			my $lookfor = "CONTENT:".$val;
			if ($tag eq $lookfor) { 
				$References{$lookfor} = shift (@ContentFiles);
			}
		}
	}
}

#read content files
foreach my $tag (@tags) {
	if ($tag =~ /^CONTENT:/) {
		my @Content = split(/\n/, ReadFile($References{$tag}) );
		#find variable tags in these files
		while ($Content[0] =~ /\<\!\-\-\#\#\#.*\=.*\#\#\#\-\-\>/ ) {
			my $line = shift @Content;
			$line =~ s/^\<\!\-\-\#\#\#//; 
			$line =~ s/$\#\#\#\-\-\>//;
			(my $eqtag, my $value) = split(/\=/, $line);
			if ($value =~ /^\"/ && $value =~ /$\"/) {
				$value =~ s/^\"//;
				$value =~ s/$\"//;
				$References{$eqtag} = $value;
			} else {
				if ($eqtag ne "SAVEAS") {
					if (!(-e $value)) { die 'ERROR: '.$References{$tag}.' contains the tag equation  {'.$line."}\n".
							      "           The file $value does not exist.\n"; }
					$References{$eqtag} = ReadFile($value);
				} else {
					$References{$eqtag} = $value;
				}
			}
		}
		$References{$tag} = join("\n", @Content);
	}
}

#Get the date
(my $D, my $M, my $Y) = (localtime)[3..5];
my @months = ("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December");
$Y += 1900;
if ($D < 10) { $D = "0".$D; }
my $Date = $months[$M]." ".$D.", ".$Y;
$References{"DATE"} = $Date;

#foreach my $key (keys %References) { print $key." = {".$References{$key}."}\n"; }

#find all tags not identified in content and assume they are file tags
foreach my $tag (@tags) {
	if (!(exists $References{$tag})) { 
		if (-e $tag) {
			$References{$tag} = ReadFile($tag);
		} else {
			die "ERROR: The file $tag does not exist and is referenced in the template.\n";
		}
	}
}

#check if there are any tags identified in the content that aren't in the template
foreach my $key (keys %References) {
	my $found = "no";
	foreach my $tag (@tags) {
		if ($key eq $tag) { $found = "yes"; }
	}
	if ($found eq "no" && $key ne "SAVEAS") { print 'NOTICE: <!--###'.$key.'###--> is defined in a content file but not'.
					" used in the template.\n"; }
}

#Define the output file if not already done.
if (!(defined $References{"SAVEAS"})) { 
	my @nameparts = split(/\./, $ARGV[0]);
	pop @nameparts;
	push (@nameparts, "html");
	$References{"SAVEAS"} = join(".", @nameparts);
}



#################################################
#################  main program  ################
#################################################

#go through the template and replace tags with their content
foreach my $line (@Template) {
	if ($line =~ /\<\!\-\-\#\#\#.*\#\#\#\-\-\>/) {
		my $tag = $line;
		$tag =~ s/^\<\!\-\-\#\#\#//; 
		$tag =~ s/$\#\#\#\-\-\>//;
		$line = $References{$tag}
	}
}

print "  Output: ".$References{"SAVEAS"}."\n";

#save the file
open (OUTFILE, ">".$References{"SAVEAS"}) or die "Could not open ".$References{"SAVEAS"}." for writing.\nERROR:$!\n";
foreach (@Template) {
	print OUTFILE "$_\n";
}
close (OUTFILE);

#Go back to the original directory
chdir($PWD);

########################################################################
#
#  Read File - This sub reads a file returns it as a string
#	USAGE: $content = ReadFile($filename);
#	       @content = split(/\n/, ReadFile($filename) );
########################################################################
sub ReadFile {
	my $filename = shift;
	#open the file
	open (INFILE, $filename) or die "Could not open $filename for input.\nERROR:$!\n";

	#get the contents
	my @contents = <INFILE>;

	#close the file
	close (INFILE);

	my $retval = "";
	#print the contents to the screen
	foreach my $line (@contents) { chomp $line; $retval = $retval.$line."\n"; }

	return $retval;
}
