#!/usr/local/bin/perl -w

# matlab_method.pl

# Program to read in data formatted as Matlab binary files.

# All necessary run-time and configuration values are read in from
# 		$config_param{'send_mail_option'}
# a configuration file specified as the first argument in the command
# line.

# Assumptions:
#	1. At least one field name must be provided, as well as the 
# Matlab, binary, data file name.

$version="V1.00 May 7, 2001";

# may 7, 2001.  V1.00  R. Groman

$| = 1;
$error = "&x";
$warning = "#";

$date = scalar localtime;
$day_today = (localtime)[6];
$day_today++;
$month_today = (localtime)[4];
$month_today++;
$year_today = (localtime)[5];
if ($year_today < 1000) {$year_today = $year_today + 1900;}
$hour_today = (localtime)[2];
if ($hour_today < 10 ) {$hour_today = "0" . $hour_today;}
$minute_today = (localtime)[1];
if ($minute_today < 10 ) {$minute_today = "0" . $minute_today;}
$time_today = $hour_today . $minute_today;
$time_stamp = $year_today . $month_today . $day_today . $time_today;
$processid = getppid;

$configuration_file = $ARGV[0];

print STDOUT ("\n#Program $0 Version: $version\n");
print STDOUT ("#  configuration file is $configuration_file\n") if defined $configuration_file;
print STDOUT ("#  Date of run: ", $date, "\n\n");

@required = (
	"field_name_1", 
	"matlab_command",
	"mat_file_names");

&read_configuration_file($configuration_file);

$debug = 'no';
if (exists $config_param{'debug'} and defined $config_param{'debug'} ) {
	if ($config_param{'debug'} =~ m/^y/i or 
	   $config_param{'debug'} =~ m/^1/ or 
	   $config_param{'debug'} =~ m/^t/i) {;
		$debug = "yes";
	}
}
&make_log_entry (">>>>>>>Begin Program=$0",
	"Date of run=$date\tVersion=$version",
	"Configuration file=$configuration_file");

$okay = "yes";
for ($i=0; $i<=$#required; $i++) {
	unless (exists $config_param{$required[$i]} ) { 
	   $okay="no"; 
	   &sendmessage ($error,
	   	"$required[$i] is missing from configuration ",
	   	"file=$configuration_file");
	   &make_log_entry ("$required[$i] is missing from configuration file",
	   	"file=$configuration_file");
	}
	else {
#		print STDOUT ("#  $required[$i]=$config_param{$required[$i]}\n");
		&make_log_entry ("$required[$i]=$config_param{$required[$i]}");
	}
}
if ( $okay eq "no") { 
	&sendmessage ($error,
		"One or more parameters are missing from the configuration file",
		"Cannot continue.");
	&make_log_entry (
		"One or more parameters missing from configuration file=$configuration_file");
	exit;
}


&process_data;

undef $error;
undef $warning;
undef $version;
undef $time_stamp;

&make_log_entry ("<<<<<<<End of $0");

exit;

#------------------------------------------------------------------------
sub read_configuration_file {

# Open and read configuration file specified as first passed parameter 
# $_[0]. Return the contents of the file as the hash array %config_param.
# Lines beginning with "#" are treated as comments.  It is assumed
# that the indirect file contains lines as

#	parameter = value

# and this information is stored as 

#	$config_param{"parameter"} = value

my $filename = $_[0];
my ($parameter, $value);

#print STDOUT ("#**debug, indirect filename=$filename\n");

unless (defined $filename ) {
	&sendmessage ($error,
		"Could not open configuration file",
		"File name not specified.  Cannot continue.");
	exit;
}
unless (open CONFIG_FILE, $filename) {
	&sendmessage ($error,
		"Could not open configuration file=$filename",
		"Error code=$!.  Cannot continue.");
	exit;
}
while (<CONFIG_FILE>) {
	chomp;
	s/\s//g;
	if (m/^#/) { next;}
	unless ( m/\S+/ ) {next;}
	unless ( m/:=/ ) {
		&sendmessage ($warning,
			"No equal sign in line of configuration file=$filename",
			"Line is=$_");
		next;
	}
#	print STDOUT ("***debug, config input line=$_\n");
	($parameter, $value) = split /:=/;
	$config_param{$parameter} = $value;
#	print STDOUT ("#**debug, config_param{$parameter}=",
#		$config_param{$parameter}, "\n");
}
close CONFIG_FILE;
}

#------------------------------------------------------------------------

sub sendmessage {

#Send a message to the user.
#The message sent will be in the strings $_[0] and $_[1]

my ( @args, $mailfile, $message0, $message1, $prefix, $who);
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst);

$prefix=$_[0];
$message0=$_[1];
$message1=$_[2];
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
if ($year >= 100 and $year <= 1000) {$year = $year + 1900}
if ($year < 1900) { $year = $year + 2000; }
$mon++;
if ($mon < 10) { $mon = "0" . $mon; }
if ($mday < 10) {$mday = "0" . $mday; }
if ($hour < 10) { $hour = "0" . $hour; }
if ($min < 10) { $min = "0" . $min; }
if ($sec < 10) { $sec = "0" . $sec; }
undef $wday;
undef $isdst;
$mailfile="/tmp/sendmess" . $year . $yday . $hour . $min . $sec . ".tmp";
if ( -e $mailfile) { unlink $mailfile }

if ( open TEMPFILE, ">$mailfile") {
	print TEMPFILE ("Message from $0\n");
	if ( exists $ENV{'REMOTE_HOST'} ) {$who=$ENV{'REMOTE_HOST'} ; }
	elsif (exists $ENV{'REMOTE_ADDR'} ) {$who=$ENV{'REMOTE_ADDR'} ; }
	else {$who="not available"; }
	print TEMPFILE (" Date of message: $year/$mon/$mday $hour:$min\n");
	print TEMPFILE (" From: $who\n");
	print TEMPFILE (" $message0\n");
	print TEMPFILE (" $message1\n");
	close TEMPFILE;
	`/bin/mail -s "Probem with $0" dmo\@globec.whoi.edu <$mailfile`;
	unlink $mailfile;
}

print STDOUT ($prefix," $message0\n");
print STDOUT ($prefix," $message1\n");
print STDOUT ($prefix," Above message from $0\n");
print STDOUT ($prefix," Date of message: $year/$mon/$mday $hour:$min\n");

return 0;
}

#----------------------------------------------------------------------------
sub process_data {

# Process the data from the file(s) specified in $config_param{'mat_file_names'}
# for the field names specified in $config_param{'field_name_<n>'}.

my (
	$command,
	@data_array, 
	@field_name, 
	@file, $file,
	$i,
	@input_structure,
	$last_value,
	$output_file,
	@output_format,
	@input_position,
	$stuff, 
	);

# Create empty Matlab file

$output_file = 'mat_method_' . $processid . '_' . $time_stamp . '.m';

if (exists $config_param{'output_file_name_root'} and 
   defined $config_param{'output_file_name_root'} ) {
	$output_file = $config_param{'output_file_name_root'} . '/' .$output_file;
}
else {
	$output_file =  '/tmp/' .$output_file;
}
print STDOUT ("#***debug, output file=$output_file\n") if $debug eq "yes";

unless (open MAT_METHOD, ">$output_file") {
	&make_log_entry ("Could not open output Matlab file=$output_file");
	&sendmessage ('error', 
		"Could not open output Matlab file $output_file",
		"Cannot continue.");
	exit;
}

# Get input file names and add LOAD command to m file.

@file = split /\s/, $config_param{'mat_file_names'};
print STDOUT ("#***debug,  file(s)=@file\n") if $debug eq "yes";

print MAT_METHOD ("% Matlab method m file created $time_stamp\n");

print MAT_METHOD ("fprintf(1,\'%s\',\'START OUTPUT NEXT LINE\')\n");

foreach $file (@file) {
	unless ( -e $file and -r $file) {
		&make_log_entry ("Cannot find or read input file=$file");
		&sendmessage ('error', "Cannot find or read input file=$file",
			"Cannot continue");
		exit;
	}
	print MAT_METHOD ("load $file;\n");
}

# Add special commands to execute if in conf file as config_param{command_<n>}

$i=1;
while (exists $config_param{"command_$i"} and 
   defined $config_param{"command_$i"} ) {
   	print MAT_METHOD ($config_param{"command_$i"},"\n");
   	$i++;
}

	
# Split up $config_param{'field_name_<n>'}

$i = 1;

while (exists $config_param{"field_name_$i"} and 
   defined $config_param{"field_name_$i"} ) {
	($data_array[$i], $field_name[$i], 
	   $input_position[$i], $input_structure[$i], $output_format[$i], 
	   $stuff) = split /,/, 
	   	$config_param{"field_name_$i"};
	unless (defined $data_array[$i] and defined $field_name[$i] and
	   defined $input_position[$i] and defined $input_structure[$i]
	   and defined $output_format[$i] ) {
	   	&make_log_entry ("Input data parameter not defined in field name=$1");
	   	&sendmessage ('error', "Input data parameter not defined.",
	   		"Check field name # $i");
	   	exit;
	}
	unless (lc $input_structure[$i] eq "array" or 
	  lc $input_structure[$i] eq "vector" ) {
		&make_log_entry ("Input structure not valid=$input_structure[$i]");
		&sendmessage ('error', "Input structure not valid as array or vector",
			"Specified as $input_structure[$i]");
		exit;
	}
	$last_value = $i;
	$i++;
}

# Output field names to standard out
for ($i=1; $i <= $last_value; $i++) {
	if (defined $field_name[$i]) {
		print STDOUT ("$field_name[$i]\t");
	}
}
print STDOUT ("\n");

# Write loop in output file

print MAT_METHOD ("for i=1:length($data_array[1])\n");

for ($i=1; $i <= $last_value; $i++ ) {
	unless ( defined $output_format[$i] and 
	  defined $input_structure[$i]) {next }
	print MAT_METHOD ("\tfprintf(1,\'$output_format[$i]\t\',",
		"$data_array[$i](");
	if ( lc $input_structure[$i] eq "array" ) {
		print MAT_METHOD ("i,$input_position[$i]))\n");
	}
	else {
		print MAT_METHOD ('i))',"\n");
	}
	print STDOUT ("#***debug, input_structure[$i]=",
		$input_structure[$i], "\n") if $debug eq 'yes';
	print STDOUT ("#***debug, output_format[$i]=$output_format[$i]",
		"\n") if $debug eq 'yes';
	
}
print MAT_METHOD ("\tfprintf(1,\'\\n\');","\nend\n");
close MAT_METHOD;

#May need to strip off beginning and ending stuff from input stream

$command = $config_param{'matlab_command'};

# Output data loop via "reading" matlab output.  Look first for special start
# string.

unless (open MATLAB_IN, "$command -nosplash -nodesktop < $output_file |") {
	&make_log_entry ("Could not open Matlab for input using=$command");
	&sendmessage($error,"Could not open Matlab for input using=$command",
		"Cannot continue.");
	exit;
}

$ready = 'no';

while (<MATLAB_IN>) {
	if ($ready eq 'yes') {
		if (m/^>>/  ) { last}
		print STDOUT ($_);
	}
	else {
		if ( m/START OUTPUT NEXT LINE/ ) {
			$ready = 'yes';
		}
	}
}	

close MATLAB_IN	;
unlink $output_file unless $debug eq 'yes';
return;
}

#-----------------------------------------------------------------------
sub make_log_entry {

# Make a log entry with @_ if the log file $config_param{"logfile"} 
# exists.  Each entry in @_ are separated by tabs.

my ($login, @month, $temp);
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst);

($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
if ($year >= 100 and $year <= 1000) {$year = $year + 1900}
if ($year < 1900) { $year = $year + 2000; }
$mon++;
if ($mon < 10) { $mon = "0" . $mon; }
if ($mday < 10) {$mday = "0" . $mday; }
if ($hour < 10) { $hour = "0" . $hour; }
if ($min < 10) { $min = "0" . $min; }
if ($sec < 10) { $sec = "0" . $sec; }

if (exists $config_param{"logfile"} ) {
	$temp = ">>" . $config_param{'logfile'};
	unless ( open LOGFILE, $temp ) {
		&sendmessage ($warning, "Could not open logfile=$temp",
			"Error code=$!");
	}
	else {
		$login = getlogin || (getpwuid($<))[0] || "Intruder!!";
		$login="\tusername=" . $login;
		print LOGFILE ($year, "/" . $mon . "/" . $mday . ":" . $hour . $min . "." . 
			$sec, $login);
		foreach (@_) {
			print LOGFILE ("\t", $_);
		}
		print LOGFILE ("\n");
		close LOGFILE;
	}
}
return;
}


#-----------------------------------------------------------------

sub mailmessage {

# Send an email message to $_[0].  

#	 $_[0] - address(es) of receiptiants
# 	 $_[1] - message (multiple lines of text)

my ( $mailfile, $message, $who);
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst);

$sendee = $_[0];
$message = $_[1];

($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
if ( $year < 1000 ) {$year = $year + 1900; }
$mon++;
if ($mon < 10) { $mon = "0" . $mon; }
if ($mday < 10) {$mday = "0" . $mday; }
if ($hour < 10) { $hour = "0" . $hour; }
if ($min < 10) { $min = "0" . $min; }
if ($sec < 10) { $sec = "0" . $sec; }
$mailfile=">/tmp/sendmess" . $year . $yday . $hour . $min . $sec . ".tmp";

if ( open TEMPFILE, $mailfile) {
	if ( exists $ENV{'REMOTE_HOST'} ) {$who=$ENV{'REMOTE_HOST'} ; }
	elsif (exists $ENV{'REMOTE_ADDR'} ) {$who=$ENV{'REMOTE_ADDR'} ; }
	else {$who="not available"; }
	print TEMPFILE ("Message from $0");
	print TEMPFILE (" Date of message: $year/$mon/$mday $hour:$min\n");
	print TEMPFILE (" From host: $who\n");
	print TEMPFILE (" Message text:\n$message\n");
	close TEMPFILE;
	$sendee =~ s/\@/\\\@/;
	`/usr/bin/mail -s \"FleetLink message\" $sendee <$mailfile`;
	unlink $mailfile;
}
return;
}

#----------------------------------------------------------------------
