#!/usr/bin/perl -I/usr/local/teamfile/tfsplugin/lib/perl
#
# $Id$
#-------------------------------------------------------------------------------
# TeamFile scheduler script
#
# Copyright (c) BAYBITS LLC, All rights reserved.
#-------------------------------------------------------------------------------
use strict;
use utf8;
use POSIX qw(strftime setlocale LC_TIME);
use File::Temp qw/ tempfile /;
use LWP::UserAgent;
use Encode;
use TF::XMLUtils;
use TF::CommonUtils;
use Getopt::Long;

require "/usr/local/teamfile/www/bin/mt-lib.pl";

# global
my $LOG_FILE    = getJobsWorkPath() . '/reportbuilder.log';
my $LOCK_FILE   = getLogPath() . '/reportbuilder.pid';
my $F_LOG       = undef;
my $CONFIG_PATH = getConfigPath();
my $BINDIR      = getApacheHome() . "/bin";

my $opt_h       = undef;
my $opt_f       = 0;

setlocale(LC_TIME, "C");

# get argument
my $ret = GetOptions("h" => \$opt_h, "f" => \$opt_f);

if ($opt_h) {
	usage();
	exit(0);
}

main();

#
# main
#
sub main {
	my $now = time();
	my $doRun = 0;

	# check Lock
	if ((my $pid = lockScript($LOCK_FILE)) != 0) {
		printerr("This script had been already started.");
		printerr('If NOT, Please check ' . $pid . ' process and remove ' . $LOCK_FILE . ' file manually.');
		return 1;
	}

	# Initialize logfile
	initLog();

	# read TeamFile configuration
	my %gparams = readTfGlobalSettings();

	my @configfiles = getReportSettingsFiles();
	my %params = ();
	foreach my $f (@configfiles){
		%params = readSettingsFile($f);
		if ($params{from} =~ /^$/) {
			# skip empty mailaddress
			writeLcLog($params{hostname}, $params{location}, "empty From address skipped");
			next;
		}
		if ($params{to} =~ /^$/) {
			# skip empty mailaddress
			writeLcLog($params{hostname}, $params{location}, "empty To address skipped");
			next;
		}
		if ($params{active} eq 0) {
			# skip inactive
			writeLcLog($params{hostname}, $params{location}, "Inactive");
			next;
		};

		my $lfile = "new_" . $params{location} . ".conf";
		my $location_file = $CONFIG_PATH . "/" . $lfile;
		next if (! -e $location_file);

		my %lcparams = parseLocationConf($lfile, \%gparams);
		my %mailparams = ();
		# run 
		my $xml = `$BINDIR/sumlocation -f $location_file`;
		my $parser = new XML::DOM::Parser;
		my $doc = $parser->parse($xml);

		for my $elem ($doc->getElementsByTagName("result") ) {
			my $nodelist = $elem->getElementsByTagName("success");
			if ($nodelist && $nodelist->getLength > 0) {
				next;
			}
		}

		for my $elem ( $doc->getElementsByTagName("storage") ){
			$mailparams{max_st}  = TF::XMLUtils::getText($elem, "max");
			$mailparams{used_st} = TF::XMLUtils::getText($elem, "used");
			$mailparams{max_st_pre} = TF::XMLUtils::getText($elem, "max_pre");
			$mailparams{used_st_pre} = TF::XMLUtils::getText($elem, "used_pre");
		}

		$doRun = 0;
		if ($params{trigger} =~ /daily/) {
			$doRun = 1;
		} elsif ($mailparams{max_st} > 0) {

			# 容量チェック
			if ($params{stg_limit} ne "") {
				my $limit = $params{stg_limit} * 1024 * 1024 * 1024;
				if ($limit >= $mailparams{max_st} - $mailparams{used_st}) {
					$doRun = 1;
				}
			}

			# 使用率チェック
			if ($params{stg_limit_per} ne "") {
				my $per = $mailparams{used_st} / $mailparams{max_st} * 100;
				if ($per >= $params{stg_limit_per}) {
					$doRun = 1;
				}

			}
		}

		if ((isItTimeToRunJob($now, $params{hour}, $params{min}) && $doRun) || $opt_f) {
			submitMail(\%mailparams, \%lcparams, \%params);
		}
		else {
			writeLcLog($params{hostname}, $params{location}, "skipped");
		}
	}
	
	closeLog();
	unlockScript($LOCK_FILE);

}

#
# Initialize logfile
#
sub initLog {
	open F_LOG, ">", $LOG_FILE;
}

#
# write logfile
#
sub writeLog {
	my $msg = shift || '';

	if (!$msg) {
		return;
	}

	my $ctime = localtime(time);
	print F_LOG $ctime . ' : ' . $msg . "\n";
}

#
# write location log
#
sub writeLcLog {
	my $hostname = shift || '';
	my $location = shift || '';
	my $msg = shift || '';
	if (!$location || !$msg) {
		return;
	}
	writeLog("[" . $hostname . "] [" . $location . "]\t\t: " . $msg);
}

#
# Finalize logfile
#
sub closeLog {
	close F_LOG;
}


# 
# getReportSettingsfiles
#
sub getReportSettingsFiles {

	my @files = ();
	my $reportdir = getConfigPath() . '/report/';
	opendir my $dh, $reportdir or die "$reportdir: $!";
	while (my $f = readdir $dh) {
		next if -d $f;	# skip directory
		next if $f =~ /\.{1,2}$/;
		next if $f =~ /bak$/;
		my @names = split(/\./, $f);
		if ($#names+1 > 2) {
			#ホスト名が含まれたファイル名をロケーション名だけに
			#リネームします。
			my $old = "$reportdir$f";
			$f = join('.', splice(@names, $#names-2));
			my $new = "$reportdir$f";
			rename($old, $new);
		}
		push(@files, "$reportdir$f"); # add full path
	}
	closedir $dh;

	return @files;
}

#
# Read settings file
#
sub readSettingsFile {
	my $filepath   = shift || '';

	if (!$filepath) {
		return;
	}

	my $isActive = 0;
	my $hour     = '';
	my $min      = '';
	my $from     = '';
	my $to       = '';
	my $hostname = '';
	my $location = '';
	my $subject  = '';
	my $phsubject= '';
	my $datetimefmt = '';
	my $trigger = '';
	my $stg_limit = '';
	my $stg_limit_per = '';

	if (-f $filepath) {
		my $xml = new XML::DOM::Parser;
		my $doc = $xml->parsefile($filepath);

		for my $elem ( $doc->getElementsByTagName("state") ) {
			my $nodelist = $elem->getElementsByTagName("active");
			if ($nodelist && $nodelist->getLength > 0) {
				$isActive = 1;
			}
			else {
				$isActive = 0;
			}
		}

		for my $elem ( $doc->getElementsByTagName("starttime") ) {
			$hour = TF::XMLUtils::getText($elem,"hour");
			$min  = TF::XMLUtils::getText($elem,"minutes");
		}

		for my $elem ( $doc->getElementsByTagName("mail") ) {
			$from = TF::XMLUtils::getText($elem, "from");
			$to = TF::XMLUtils::getText($elem, "to");
		}

		for my $elem ( $doc->getElementsByTagName("reportsetting") ) {
			$hostname    = TF::XMLUtils::getText($elem, "hostname");
			$location    = TF::XMLUtils::getText($elem, "location");
			$subject     = TF::XMLUtils::getText($elem, "subject");
			$phsubject   = TF::XMLUtils::getText($elem, "phsubject");
			$datetimefmt = TF::XMLUtils::getText($elem, "datetimefmt");
			$trigger     = TF::XMLUtils::getText($elem, "trigger");
			$stg_limit   = TF::XMLUtils::getText($elem, "stg-limit");
			$stg_limit_per = TF::XMLUtils::getText($elem, "stg-limit-per");
		}

		$doc->dispose;
	}

	my %params =	(	active => $isActive,
						hour   => $hour,
						min    => $min,
						from   => $from,
						to     => $to,
						hostname => $hostname,
						location => $location,
						subject  => $subject,
						phsubject=> $phsubject,
						datetimefmt => $datetimefmt,
						trigger => $trigger,
						stg_limit => $stg_limit,
						stg_limit_per => $stg_limit_per,
					);
	return %params;
}

#
# comma delimitation
#
sub commaDelimitation {

	my $value = shift;
	1 while $value =~ s/(.*\d)(\d\d\d)/$1,$2/;

	return $value;

}

#
# submitMail
#
sub submitMail {

	my $mail = shift;    # mail body param
	my $conf = shift;    # location config param
	my $repconf = shift; # report setting param

	my $subject = $$repconf{subject} || $$repconf{phsubject};

	my @datetimefmt = ( 
		{ value => "default",    format => "%Y-%m-%d %H:%M:%S" },
		{ value => "yyyy-mm-dd", format => "%Y-%m-%d %I:%M:%S %p"},
		{ value => "mm/dd/yyyy", format => "%m/%d/%Y %I:%M:%S %p"},
		{ value => "dd/mm/yyyy", format => "%d/%m/%Y %I:%M:%S %p"}
	);

	my $dtformat = "%Y-%m-%d %H:%M:%S"; # default

	foreach my $fmts (@datetimefmt) {
		if ($fmts->{'value'} eq $repconf->{datetimefmt}) {
			$dtformat = $fmts->{'format'};
		}
	}
	my $now_str = strftime $dtformat , localtime();

	my ($fh, $filename) = tempfile(UNLINK =>1);
#                                   DIR => getTmpScriptPath());

	# comma delimitation
	$$mail{used_st} = commaDelimitation($$mail{used_st});
	$$mail{max_st}  = commaDelimitation($$mail{max_st});

	# pretty format split
	my ($cap, $unit) = split(/ /, $$mail{used_st_pre});
	$$mail{used_st_pre} = commaDelimitation($cap) . " " . $unit;
	my ($cap, $unit) = split(/ /, $$mail{max_st_pre});
	$$mail{max_st_pre} = commaDelimitation($cap) . " " . $unit;

	if ($$mail{max_st} eq 0) {
		$$mail{max_st} = $$mail{max_st_pre} = "unlimited";
	}

	print $fh "====================\n";
	print $fh "$now_str\n";
	print $fh "====================\n";
	print $fh "Hostname : $$repconf{hostname}\n";
	print $fh "Location : $$repconf{location}\n";
	print $fh "\n";
	print $fh "storage\n";
	print $fh "  max  : $$mail{max_st_pre} ($$mail{max_st})\n";
	print $fh "  used : $$mail{used_st_pre} ($$mail{used_st})\n";

	close($fh);

	my @toArray = split(/,/, $$repconf{to});
	foreach(@toArray) {
		my $result = `$BINDIR/sendmail.pl --host=$$conf{mailhost} --port=$$conf{mailport} --from=$$repconf{from} --to=$_ --subject="$subject" --msgf="$filename"`;
	}

	writeLcLog($$repconf{hostname}, $$repconf{location}, "mail Send");

}

#
# Show usage
#
sub usage {
	print <<"_EOF_";
Usage: reportbuilder [-f] | [-h]
       -f : force execute
       -h : Show usage
_EOF_
}

