#!/usr/bin/perl -T

# Copyright (C) 2012-2016 by Debian Edu project, http://wiki.debian.org/DebianEdu
#       Mike Gabriel <mike.gabriel@das-netzwerkteam.de>

# 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.,
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.

use strict;
use warnings;
use Cwd;
use File::Basename;
use File::Spec;
use Archive::Zip qw(:ERROR_CODES :CONSTANTS);
use Text::CSV;
use Getopt::Long;

$ENV{PATH} = '/usr/bin:/bin';

my $usage = '';
my $do_zip = '';
my $do_debug = '';
my $template = 'students';
my $zipfile_name = basename(&Cwd::cwd())."-TEMPLATE.zip";
my $rows = '7';
my $cols = '3';
GetOptions ('help' => \$usage,
            'template=s' => \$template,
            'zip' => \$do_zip,
            'zipfilename=s' => \$zipfile_name,
            'rows=s' => \$rows,
            'cols=s' => \$cols, 
            'debug' => \$do_debug,
);

$zipfile_name =~ s/TEMPLATE/$template/;

sub get_file_content {

	my $filename = "@_ ";
	$filename =~ s/^\s+|\s+$//g ;

	my $fullpath;

	if ( -f $ENV{"HOME"}.'/.'.basename($0).'/'.$filename ) {
		$fullpath = $ENV{"HOME"}.'/.'.basename($0).'/'.$filename;
	}
	elsif ( -f File::Spec->rel2abs("$filename") ) {
		$fullpath = File::Spec->rel2abs("$filename");
	}
	elsif ( -f '/etc/'.basename($0).'/'.$filename ) {
		$fullpath = '~/.'.basename($0).'/'.$filename;
	}
	elsif ( -f '/usr/local/share/'.basename($0).'/'.$filename ) {
		$fullpath = '/usr/local/share/'.basename($0).'/'.$filename;
	}
	elsif ( -f '/usr/share/'.basename($0).'/'.$filename ) {
		$fullpath = '/usr/share/'.basename($0).'/'.$filename;
	}
	else
	{
		return ();
	}

	open FH, $fullpath;
	print "Using: ".$fullpath."\n";
	my @content = <FH>;
	close FH;
	return @content;

}

sub finalize_texheader {

    my $line = "@_ ";

    $line =~ s/@@@\_ROWS_@@@/$rows/g;
    $line =~ s/@@@\_COLS_@@@/$cols/g;

    return $line;
}

sub usage {
	print "usage: ".basename($0)." [options] <CSV-file-1> [<CSV-file-2> [...]]\n";
	print "\n";
	print "Options:\n";
	print "    --help                        -- show this help output.\n";
	print "    --template=<tpl-name>         -- name of the template to use.\n";
	print "    --cols=<x>                    -- render <x> columns per sheet\n";
	print "    --rows=<y>                    -- render <y> rows per sheet\n";
	print "    --zip                         -- do create a ZIP file at the end\n";
	print "    --zipfilename=<zip-file-name> -- alternative ZIP file name (default: name of parent folder)\n";
	print "    --debug                       -- don't remove temporary files\n";
	print "\n";
	print "CSV File Column Arrangement\n";
	print "---------------------------\n";
	print "\n";
	print "The ".basename($0)." tool can handle any sort of column arrangement in given CSV file(s).\n";
	print "It expects the CSV file(s) to have column names in their first line.\n";
	print "\n";
	print "The given column names have to map to the \"VAR-<column-name>\" placeholders in ".basename($0)."'s\n";
	print "LaTeX templates.\n";
	print "\n";
	print "The shipped-with templates (\"stundents\", \"teachers\") can handle these column names:\n";
	print "\n";
	print "	login:		The user account's login id (uid)\n";
	print "	lastName:	The user's last name(s)\n";
	print "	firstName:	The user's first name(s)\n";
	print "	password:	The user's password\n";
	print "	form:		The form name/ID (student template only)\n";
	print "	subjects:	A list of subjects taught by a teacher (teacher template only)\n";
	print "\n";
	print "If you create your own templates, you can be very flexible in using your own column names and template\n.";
	print "names. Only make sure that the column names provided in the CSV file(s) match the variables used in the\n";
	print "customized LaTeX template.\n";
	print "\n";
	print "The shipped-with ".basename($0)." templates can be found in /usr/share/".basename($0)."/.\n";
	print "When customizing templates, simply place them into ~/.".basename($0)."/ or /etc/".basename($0).".\n";
	print "\n";

	exit 0;
}

if ( $usage ) { usage() };

if ( (scalar @ARGV) == 0 ) {
	print "ERROR: No CSV file(s) name given. Aborting...\n\n";
	usage();
};

my $zip;
if ( $do_zip ) {
	print "preparing ZIP archive file: $zipfile_name\n";
	$zip = Archive::Zip->new();
}

my @template = get_file_content($template."-template.tex") or die $!;
my @tex_header = get_file_content("header.tex") or die $!;
my @tex_footer = get_file_content("footer.tex") or die $!;

my $csv_file;
my $csv_filehandle;
my $tex_file;
my $pdf_file;
my $log_file;
my $aux_file;
my $csv_table;

my $this_template;

while ( @ARGV )
{
	$csv_file = shift;
	$csv_file =~ s/^\s+|\s+$//g ;

	if ( $csv_file =~ /^(.*)$/ && -f $csv_file ) {

		$tex_file = $1;
		$tex_file =~ s/.csv/.tex/;

		print "Processing: ".File::Spec->rel2abs($csv_file)."\n";

		$pdf_file = $csv_file;
		$pdf_file =~ s/.csv/.pdf/;

		$log_file = $csv_file;
		$log_file =~ s/.csv/.log/;

		$aux_file = $csv_file;
		$aux_file =~ s/.csv/.aux/;

		$csv_table = Text::CSV->new({
		    decode_utf8=>0,
		    binary => 1,
		    auto_diag => 1,
		});
		open $csv_filehandle, "<$csv_file";

		open TEXFILE, ">$tex_file";
		foreach (@tex_header) {
			print TEXFILE finalize_texheader($_)."\n";
		}

		$csv_table->column_names($csv_table->getline ($csv_filehandle)); # use header
		while (my $row = $csv_table->getline_hr($csv_filehandle)) {
			$this_template = join("", @template);
			while (my ($key, $value) = each %$row) {
				$key =~ s/^\s+|\s+$//g ;
				if (!$key) {
					next;
				}
				$value =~ s/^\s+|\s+$//g ;
				$this_template =~ s/VAR-$key/$value/;
			}
			print TEXFILE "$this_template";
		}

		close $csv_filehandle;

		foreach (@tex_footer) {
			print TEXFILE "$_\n";
		}

		close TEXFILE;

		print "Created temporary file: ".File::Spec->rel2abs($tex_file)."\n";
		if ( system("/usr/bin/pdflatex --halt-on-error $tex_file 2>&1 1>/dev/null") == 0 ) {
			print "Rendered: ".File::Spec->rel2abs($pdf_file)."\n";
			if ( ! $do_debug ) {
				if ( -e $tex_file && $tex_file =~ /^(.*)$/ ) { print "Removing temporary file: ".$1."\n"; unlink($1); }
				if ( -e $log_file && $log_file =~ /^(.*)$/ ) { print "Removing temporary file: ".$1."\n"; unlink($1); }
				if ( -e $aux_file && $aux_file =~ /^(.*)$/ ) { print "Removing temporary file: ".$1."\n"; unlink($1); }
			}
		}
		else
		{
			print "Rendering FAILED: ".File::Spec->rel2abs($pdf_file).", see .log and .aux file for details.\n";
		}

		if ( $do_zip ) {
			print "writing CSV sheet to ZIP archive\n";
			$zip->addFile( $csv_file ) or warn "Can't add file $csv_file\n";
			print "writing PDF file to ZIP archive\n";
			$zip->addFile( $pdf_file ) or warn "Can't add file $pdf_file\n";
		}

	}
	else
	{
		print "NO SUCH FILE: ".$csv_file."\n";
	}
}

if ( $do_zip ) {
	my $status = $zip->writeToFileNamed($zipfile_name);
	print "ZIP archive $zipfile_name closed\n";
	exit $status;
}
