#!/usr/bin/perl

use File::Copy;
use IO::File;
use Data::Dumper;

#---------------------------------------------------------------------------------------
# 17 Jun 11		A1C David Baker 		GFSGAPS has been changed to run 4x a day. (00z,06z,12z,18z)
#										
#	#1 - Added date rollover check for expiring cycles that have not run.
#	#2 - Added a check to stop the script from running into the next cycle. If the current cycle does not have all
#		 input files and it is within a half hour of the next cycle, a critical Tivoli is thrown and the current cycle
#		 is stopped to prevent overlapping with the next cycle.
#	#4 - Added new functionality to reliably create log files. Data is appended to the same log for the 
#		 current cycle and process ID. Logfiles naming scheme:
#						
#	GFSGAPS/data/logs/GFSGAPS_CC_DDMM_PID
#	CC - Cycle time
#	DD - Day
#	MM - Month
#	PID - Process ID
#
#---------------------------------------------------------------------------------------
# 23 June 11	A1C David Baker			GFSGAPS has been modified to run standalone.
#
##1 - All calls to call_tivoli have been commented out and, where necessary, they have been replaced with a log entry of the error.
#				
#Essential Notes:
#- GFSGAPS.cfg must be updated with the correct paths for GFSGAPS.pl to run correctly.
#- wgrib must be located at /opt/production/apps/utilities/wgrib (editable on line 214)
#- Naming convention for input files is (~line 209): PS.NCEP_SC.U_DI.A_GP.GFS_GR.C1DEG_AR.GLOBAL_PA.GFSGAPS_CY.${Cur_cycle}_FH.0${fc_hour}_DF.GR1
#	${Cur_cycle} = Current cycle in 2 digit format.
#	${fc_hour} = Forecast hour in 2 digit format. Notice another zero is prepended to the 2 digit forcast hour as seen above.
#
#


#cause print buffer to auto dump
$| = 1;

#Ensure arguments are supplied
if($ARGV[0] eq "" || $ARGV[1] eq "" || $ARGV[2] eq ""){
	print "\nUsage: GFSGAPS.pl 'cycle' 'config file path' 'Path to Working Directory' \n\n";
	exit(99);
}

#Set config file to the script argument
$Cur_cycle = $ARGV[0];
$CFG = $ARGV[1];
$Work_dir = $ARGV[2];

################################################################################
#  Set up log file and redirect (select) STDOUT to log file
################################################################################
my %config = %{get_config($CFG)};
#print Dumper(\%config);
$contact = $config{'CONTACT'};
$channel = $config{'CHANNEL'};
$datestamp = `date +%d%m`;
chomp($datestamp);
#BSM $autolog = $config{'LOGDIR'} . "GFSGAPS_" . $Cur_cycle ."_" . $datestamp ."_" . $$;
$autolog = "$Work_dir/log/" . "GFSGAPS_" . $Cur_cycle ."_" . $datestamp ."_" . $$;
 

umask(0022);
#OLD FILE OPEN CALL --
#$adtl = IO::File->new($autolog, "a")
	sysopen ($adtl, $autolog, O_WRONLY|O_APPEND|O_CREAT, 0755)
#	sysopen ($adtl, $autolog, O_RDWR, 0755)
		or 
		#### Commented out for Offline GFSGAPS
		#call_tivoli("C",
		#       "$contact",
		#       "${channel}0003:",
		#       "Unable to open $autolog for writing",
		#       "Permissions",
		#       "Check Permissions");
		####Added for Offline GFSGAPS
		print get_date() . " - Unable to open $autolog for writing. Check permissions.\n";
		####END Offline GFSGAPS ADDITION
select($adtl);
$adtl->autoflush(1);

print get_date() . " -------------------------------------------------------------\n";
print get_date() . " - GFSGAPS begin for ".$Cur_cycle."Z cycle\n";

#Set up directories and list of forecast hours needed
$INDIR = "$Work_dir/indata/";
#BSM $INDIR = $config{'INDIR'};
#BSM $OUTDIR = $config{'OUTDIR'};
$OUTDIR = "$Work_dir/outdata/";
#BSM $BADDIR = $config{'BADDIR'};
$BADDIR = "$Work_dir/bad/";
$BINDIR = $config{'BIN'};
#BSM $DONEDIR = $config{'DONEDIR'};
$DONEDIR = "Work_dir/done/";
$HOUR_DIFF = $config{'HOUR_DIFF'};
$XML_FILE = $config{'XML_FILE'};
$LOGDIR = "$Work_dir/log/";
#BSM $LOGDIR = $config{'LOGDIR'};
 
my $present_files = 0;

#Go until its found every forecast hour file
#Change to the input directory
#### If the directory cannot be changed to the supplied INDIR in GFSGAPS.cfg, a tivoli is thrown and we exit. Commented out for Offline GFSGAPS.
#chdir $INDIR or call_tivoli("C",
#	            	"$contact",
#		    	"${channel}0005:",
#	            	"Unable to read GFSGAPS input",
#			"Could not change directory to $INDIR",
#	            	"Rerun manually after fixing permissions or restoring directory"), exit;
#### ADDED for Offline GFSGAPS  - Just print the error to the log if we cannot read from the INDIR. OFFLINE GFSGAPS CHANGE					
chdir $INDIR or print get_date() . " - Unable to read GFSGAPS input from $INDIR\n", exit(99);
#### End Offline GFSGAPS ADDITION
					

print get_date() . " - changed to $INDIR\n";
#---------------------------------------------------------------------
# Sniffs for unflipped GFS files
#---------------------------------------------------------------------
# Keep looking and sleeping until we find an input file for every FCST_HOURS entry

my @array_of_filenames;

# Global variable for date_time_stamp file that is pulled from the wgrib'd file if it is the current cycle's time stamp.
my $date_time_stamp;

#while ($present_files != ($#{$config{'FCST_HOURS'}}+1)) {

  @array_of_filenames = ();

        $present_files = 0;

	# Check each FCST_HOURS entry with input files
        foreach my $fc_hour (@{$config{'FCST_HOURS'}}) {
                my $file = "PS.NCEP_SC.U_DI.A_GP.GFS_GR.C1DEG_AR.GLOBAL_PA.GFSGAPS_CY.${Cur_cycle}_FH.0${fc_hour}_DF.GR1";
                push(@array_of_filenames,$file);
		# If the FCST_HOURS entry input file is here, proceed with the wgrib check on the date/time
                #if  (-e $config{'INDIR'}.$file && (stat($config{'INDIR'}.$file))[7] > 0) {
                if  (-e $INDIR.$file && (stat($INDIR.$file))[7] > 0) {
                    my ($day,$mon,$year) = (localtime(time-(360*((localtime)[2] % $config{'HOUR_DIFF'}))))[3,4,5];
                    my @wgrib_out = split("\n", `/nwprod/util/exec/wgrib $file`);
                    #BSM my @wgrib_out = split("\n", `/opt/production/apps/utilities/wgrib $file`);
                    my $date_cluster = sprintf("%02d",($year-100)) . sprintf("%02d",($mon+1)) . sprintf("%02d",$day) . "$Cur_cycle";
                    my @good_grib = grep(/$date_cluster/, @wgrib_out);
		    # If there is a match, increment the counter and move on the array list, if there is no match then we skip this
                    if  ($#good_grib == $#wgrib_out) {
                           $present_files++;
						   #creating the date time stamp for TIMEFILE. Format is YYYYMMDDCC (YearMonthDayCycle)
						   $full_year = ((localtime)[5]) + 1900;
						   $year_prefix = substr($full_year,0,2);
						   #since the search string matched the line in the gribfile, this means this is the correct day, month, year and cycle. So this is what our TIMEFILE will be populated with.
						   $date_time_stamp = $year_prefix . $date_cluster;
                     }
		     # But if the override is set, we process anyway!
		     elsif (uc($config{'TIME_OVERRIDE'}) eq 'YES' || uc($config{'TIME_OVERRIDE'}) eq 'TRUE') {
		           $present_files++;
		     }
                }
        }

#	if  ($present_files != ($#{$config{'FCST_HOURS'}}+1)) {
#		print get_date() . " - All files not yet present " . $present_files . "/" . ($#{$config{'FCST_HOURS'}}+1) . " found\n";
#		my $offset = 0;
#		my $math_cycle = $Cur_cycle;
#		$math_cycle = 0 if ($Cur_cycle eq '00');
#		#If the day has rolled over, adjust for it
#		if  ((localtime)[2] < $math_cycle) {
#			$offset += 24;
#		}

		# Timeout if the current hour is at least $Cur_cycle + $config{'HOUR_DIFF'} and the override flag is not set. If true, the current cycle is going to end without 
		# running b/c of the lack of all input data. 
#		if  (uc($config{'TIME_OVERRIDE'}) ne 'YES' && uc($config{'TIME_OVERRIDE'}) ne 'TRUE' &&
#				(localtime)[2] + $offset >= $math_cycle + $config{'HOUR_DIFF'}) {
#			print get_date() . " - CRITICAL - " . $Cur_cycle . "Z files have not all come in for this cycle.\n";
#			print get_date() . " - CRITICAL - " . $Cur_cycle . "Z cycle is terminating due to next cycle start in 30 minutes.\n";
#			exit(99);
#		}
#		print get_date() . " - Checking again in 30 minutes\n";
#		sleep(1800);
#	}
#}

# We have all input files at this point,send each one through grib_flip one at a time
foreach $grib_file(@array_of_filenames) {
	print get_date() . " - working on input file $file\n";
        #extract current forecast hour
        $FH = substr($grib_file, 65, 2);
        #Create the new file name
        $new_file = "AFWA_GFS_$FH.grib";
        #Flip the grid of this GFS file
        $success = grid_flip($INDIR . $grib_file, $OUTDIR . $new_file, $CFG);
        #Ensure the grid flip worked correctly
        if($success != 1){
        	print get_date() . " - error flipping $grib_file\n";
        	####Commented out for Offline GFSGAPS.
			#call_tivoli("C",
        	#	"$contact",
        	#	"${channel}0007:",
        	#	"Error flipping GFS file $grib_file",
        	#	"$success",
        	#	"Rerun manually after validating input files");
        	#Move the file to some "badfiles" location
        	move_input($grib_file, $BADDIR);
        	exit(99);
	}
	print get_date() . " - successfully made $new_file\n";
}

print get_date() . " - found all files for ".$Cur_cycle."Z cycle\n";

#Create the time stamp file ACFP requires
make_time_file($CFG, $Cur_cycle);

#Send all forecast hours of the finished cycle to customers
#### Sending is not required for offline GFSGAPS. Commented out for Offline GFSGAPS.
#foreach $xml_id (@{$config{'FTP'}}){
##	send_cycle($XML_FILE, $Cur_cycle, $xml_id, 1); #This line was previously commented before Offline GFSGAPS modifications.
#        send_cycle($XML_FILE, $Cur_cycle, $xml_id);
#}

#Move the input so next cycle doesn't start with possibly old data
#BSM I don't think there's any need to do this on the CCS
#BSM move_done($DONEDIR, $Cur_cycle, 1);

#script is finished, no reason to wait the 2 minutes
print get_date() . " - GFSGAPS Finished\n";
exit;

#########################################################################


#########################################################################
#				SUBROUTINES
#########################################################################


#########################################################################

#This method reads in the GFS file and flips the
#gridding to resemble NOGAPS grib format.
sub grid_flip () {

	local($inFile, $outFile, $CFG) = @_;
	#Ensure current file IS in fact a grib file
	$isGrib = 0;
        $record_num=1;

	open (IN, "$inFile") or return "Could not read $inFile";
	open (OUT, ">$outFile")or return "Could not write to $outFile";
	binmode IN;
	binmode OUT;

	# The ordering of these determines the ordering of the output.
	# Per current ACFP IFS, the output must be in a specific parameter/level order
        @parameters = @{$config{'PARAMS'}};
        @levels = @{$config{'LEVELS'}};

	# Set the scan mode for a global grid that starts at the S pole.
	my $GDS_Scan_Mode=pack("C",64);

	my $Section0; #Section 0 of the grib file, Indicator section
	my $Section1; #Section 1 of the grib file, Product definition section(PDS)
	my $Section2; #Section 2 of the grib file, Grid description section(GDS)
	my $Section4; #Section 4 of the grib file, Binary Data Section
	my $Section5; #Section 5 of the grib file, end of record indicator

	# Flip grid
	while(read(IN,$in,1)){
		# Find the characters 'G' 'R' 'I' 'B' in running succession before proceeding
   		if($in eq 'G'){
      			read(IN,$in,1) or return "Could not read $inFile";
      		if($in eq 'R'){
         		read(IN,$in,1) or return "Could not read $inFile";
         	if($in eq 'I'){
            		read(IN,$in,1)or return "Could not read $inFile";
            	if($in eq 'B'){
                        print "Working on record $record_num\n";
                        $record_num++;
	           	# Read GRIB Size info
               		read(IN,$in,4) or return "Can't read GRIB File size info";
               		$Section0="GRIB".$in;
                        $GRIBSize=vec($in,0,8)*256*256+vec($in,1,8)*256+vec($in,2,8);
                        if (vec($in,3,8) != 1) {
                           print "$record_num is not an actual entry, returning to scan...\n";
                           $record_num--;
                           next;
                        }
	                #It has been verified that this IS a grib file
			$isGrib = 1;
                        print "GRIBSize=$GRIBSize\n";

               		# Process PDS
               		read(IN,$in,3) or return "Can't read GRIB PDS size info";
               		$Section1=$in;
               		$in=pack("xa3",$in);
               		$PDSlength=vec($in,0,32);
                        print "pdslength=$PDSlength\n";
               		read(IN,$in,$PDSlength-3) or return "Can't read BMS in section 1"; # As First 3 bytes of Section 1 already read
               		$Section1.=$in;
               		$BMS = vec($in,4,8) & 64 ? 1 : 0;
			#Check bitmap sections existence
	           	#return "BITMAP section present but should not be\n" if ($BMS);
                        if($BMS) {
                           print "BMS present\n";
                           read (IN,$in,$GRIBSize-8-$PDSlength) or return "Can't skip BMS";
                        }
	           	next if ($BMS);
	           	$parameter=vec($in,5,8);
                        $level_type=vec($in,6,8);
	           	$level=vec($in,7,8)*256+vec($in,8,8);
                        print "parameter level $parameter $level\n";

               		# Process GDS
               		read(IN,$in,3) or return "Can't read GRIB GDS size info";
               		$Section2 = $in;
	           	$GDSlength = pack("xa3",$in);
               		$GDSlength = vec($GDSlength,0,32);
	           	read(IN,$in,7) or return "Could not read $inFile"; # Read GDS components that don't need changes
               		$Ni=vec($in,3,8)*256+vec($in,4,8); #Calculate number of points along a parallel
               		$Nj=vec($in,5,8)*256+vec($in,6,8); #Calculate number of points along a meridian
	           	return "Ni is not 360 as expected. Ni=$Ni\n" if ($Ni != 360);
	           	return "Nj is not 181 as expected. Nj=$Nj\n" if ($Nj != 181);
	           	$Section2 = $Section2 . $in;
	       	   	read(IN,$LA1,3) or return "Could not read $inFile (LA1)"; # READ LA1
	           	read(IN,$in,4) or return "Could not read $inFile"; # Stuff we don't need to change
	           	read(IN,$LA2,3) or return "Could not read $inFile (LA2)"; # READ LA2
	           	$Section2 = $Section2 . $LA2 . $in . $LA1;
	           	read(IN,$in,7) or return "Could not read $inFile"; #More stuff we don't care about
	           	$Section2 = $Section2 . $in;
	           	read(IN,$scan,1) or return "Could not read $inFile (Scan mode)"; #Read Scan mode but overwrite with proper value
	           	$Section2 = $Section2 . $GDS_Scan_Mode;
               		read(IN,$in,$GDSlength-28) or return "Could not read the rest of section 2";# As First 28 bytes of GDS already read
               		$Section2 = $Section2 . $in;

               		read(IN,$in,3) or return "Can't read GRIB BDS size info";
               		$BDSlength=pack("xa3",$in);
               		$BDSlength=vec($BDSlength,0,32);
               		read(IN,$in2,8) or return "Can't read GRIB BDS details";
               		$Section4 = $in . $in2;

               		$extrabit=vec($in2,0,8) & 8 ? 1 : 0;
               		$numbits=vec($in2,7,8);
               		read(IN,$grid,$BDSlength-11) or return "Could not read $inFile (grid)";# As First 11 bytes of BDS already read

               		#Flip the GRID
               		for ($j=$Nj-1;$j>=0;$j--)
               		{
	              		$Section4.=substr($grid,$j*$Ni*$numbits/8,$Ni*$numbits/8);
               		}
               		if ($extrabit)
               		{
                  		$Section4.="\000";
               		}
			read(IN,$in,4) or return "Can't read End Section";
			return "End Section not = 7777\n" if ($in ne '7777');
			$Section5=$in;
                        if ($level_type == 100) {
			         $GRIB{$parameter, $level} = $Section0 . $Section1 . $Section2 . $Section4 . $Section5;
                        }
            	}
         	}
      		}
   		}
	}
	#Output the newly flipped and ordered NOGAPS look-a-like file
	foreach $parameter (@parameters)
	{
   		foreach $level (@levels)
   		{
                        return "Missing parameter $parameter at level $level" unless (defined $GRIB{$parameter, $level});
      			print OUT $GRIB{$parameter, $level}  or return "Could not write to $outFile - $GRIB{$parameter, $level}";
   		}
	}

	#This will return 1(successful) if the current file finished flipping
	#and was found to be a valid grib format file
	if($isGrib){
		return 1;
	} else {
		return "$inFile was not a valid grib formatted file";
	}
}

############################################################################
##  Create time date stamp + cycle file required for AFCP.
sub make_time_file(){

	local($CFG, $cycle) = @_;

	#Make the time file AFCP requires
	#### Commented out for Offline GFSGAPS
	#$timefile = $config{'TIMEFILE'};
	#
	####ADDED FOR GFSGAPS Offline
	$timefile = $OUTDIR . "GFS_time_date_stamp.txt";
	#### End Offline GFSGAPS Addition
	
	#### Make the TIMEFILE (date_time_stamp.txt) or throw a Tivoli. Commented out for Offline GFSGAPS.
	#open(TIMEFILE, ">$timefile") or call_tivoli("C",
	#	        			"$contact",
	#					"${channel}0008:",
	#	        			"Could not write to $timefile",
	#	        			"Permissions",
	#	        			"Fix permissions for $timefile then rerun manually"), exit;
	#print TIMEFILE "$date_time_stamp\n\n" or call_tivoli("C",
	#	        			"$contact",
	#					"${channel}0009:",
	#	        			"Could not write to $timefile",
	#	        			"Permissions",
	#	        			"Fix permissions for $timefile then rerun manually"), exit;
	#### ADDED for Offline GFSGAPS errors sent to logs instead of throwing Tivolis.
	open(TIMEFILE, ">$timefile") or print get_date() . " - Could not write to $timefile - Fix permissions for $timefile then rerun manually\n", exit(99);
	print TIMEFILE "$date_time_stamp\n\n" or print get_date() . " - Could not write to $timefile - Fix permissions for $timefile then rerun manually\n", exit(99);
	###### END OFFLINE GFSGAPS ADDITIONS
}

###############################################################
###  Send files to the respective customer(xml_id)
###  as dictated by GFSGAPS.xml.
#sub send_cycle() {

##	local($XML_FILE, $cycle, $xml_id, $tries) = @_;
#        local($XML_FILE, $cycle, $xml_id) = @_;
#	Number of tries to ftp can be changed
	#Retrieve the required java paths to execute reuse library file sender
#	$CLASSPATH = $config{'CLASSPATH'};
	#send some files here lololol
#	`java -cp $CLASSPATH mil.af.afwa.scs.reuse.filetransfer.FileSender $XML_FILE $xml_id > temp 2>&1`;
	#Retrieve any STDERR output from temp file
#        if ($? != 0) {
#           print "\nFTP Error: $! \n";
#	if($ftp_status =~ /max retries \(\d+\) exceeded\!/) {
		#Log what specific error occurred
#		print "\nFTP_Error:\n\t $ftp_status\n\n";
#		Only throw a fit if this was the $NUM_TRY time erroring
#		if($tries < $NUM_TRY){
#			print get_date() . " - Unable to send ".$cycle."Z files to $xml_id, trying again in a minute\n";
#			sleep(60);
#			send_cycle($XML_FILE, $cycle, $xml_id, $tries+1);
#		} else {
#			print get_date() . " - Unable to send ".$cycle."Z files, sending critical tivoli\n";
			#Level 3 tivoli and quit
			
			#### Commented out for Offline GFSGAPS
			#call_tivoli("C",
		     #   	"$contact",
				#"${channel}0010:",
		        #	"Unable to send ".$cycle."Z files, sending critical tivoli",
		        #	"Not all files correctly sent!",
		        #	"Check permissions, ESS, or $xml_id config in XML\n\n$!"), exit;
#		}
#	} else {
		#We win at life
#		print get_date() . " - Successfully sent ".$cycle."Z cycle files to $xml_id\n";
#                unlink("temp");
#	}
#}

############################################################################
##  Moves a file from $INDIR/$file to $OUTDIR/$file
sub move_input()
{
	local($file, $outdir) = @_;
	#### Commented out for Offline GFSGAPS.
	#move($file, $outdir . $file) or call_tivoli("C",
	#	        			"$contact",
	#					"${channel}0011:",
	#	        			"Unable to move bad file $file to $outdir",
	#	        			"Permissions or ESS error, bad file remains in input directory",
	#	        			"Check permissions, ESS"), exit;
	####ADDED for GFSGAPS offline so error is sent to log instead of throwing a Tivoli. 
	move($file, $outdir . $file) or print get_date() . " - Unable to move bad file $file to $outdir - Permissions or ESS error, bad file remains in input directory\n", exit(99);
	####END GFSGAPS ADDITIONS
}

############################################################################
#  Move *CY.$Cur_cycle* to $DONEDIR, tries up to 3 times if unsuccessful
sub move_done()
{
	local($DONEDIR, $Cur_cycle, $tries) = @_;
        print get_date() . " - Performing backup roll-over\n";
        if ((-w "$DONEDIR/DAY1") && (-w "$DONEDIR/DAY2") && (-w "$DONEDIR/DAY3") && (-w "$DONEDIR/DAY4")) {
            $move = system("mv -f $DONEDIR\/DAY3\/*CY.$Cur_cycle* $DONEDIR\/DAY4 > /dev/null 2>&1");
            $move = system("mv -f $DONEDIR\/DAY2\/*CY.$Cur_cycle* $DONEDIR\/DAY3 > /dev/null 2>&1");
            $move = system("mv -f $DONEDIR\/DAY1\/*CY.$Cur_cycle* $DONEDIR\/DAY2 > /dev/null 2>&1");
            $move = system("mv -f $DONEDIR\/*CY.$Cur_cycle* $DONEDIR\/DAY1 > /dev/null 2>&1");
        } else {
            print get_date() . " - Cannot access $DONEDIR subdirectories, check write permissions and existance\n";
                        #### Commented out for Offline GFSGAPS.
						#call_tivoli("C",
                        #        "$contact",
                        #        "${channel}0012:",
                        #        "$Cur_cycle input was not moved to $DONEDIR",
                        #        "Move $INDIR*$Cur_cycle* manually, after correcting subsequent directories",
                        #        "Possible permissions issue or ESS issue"), 
						exit(99);
        }
	print get_date() . " - Moving ".$Cur_cycle."Z files to $DONEDIR\n";
	$move = system("mv -f *CY.$Cur_cycle* $DONEDIR");
	if($move != 0){
		if($tries < 3){
			print get_date() . " - Unable to move input to $DONEDIR, trying again in 60 secs\n",
			sleep(60),
			move_done($DONEDIR, $Cur_cycle, $tries+1);
		} else {
			print get_date() . " - Unable to move input after 3 tries, quitting\n";
			#### Commented out for Offline GFSGAPS.
			#call_tivoli("C",
		    #        	"$contact",
			#    	"${channel}0013:",
		    #        	"$Cur_cycle input was not moved to $DONEDIR",
		    #        	"Move $INDIR*$Cur_cycle* manually",
		    #        	"Possible permissions issue or ESS issue"), exit;
			exit(99);
		}
	}

}

############################################################################################
## Build configuration hash on first call, to be utilized throughout the program after built
sub get_config()
{
	local $filename = shift;
	my %config;
	#Read config file into Hash
    		open(RESULTFILE,$filename);
    		while ($result = <RESULTFILE>) {
        		$result =~ s/\n//;
        		if  ($result !~ /^#/ && $result ne "") {
            			$result =~ /^(.+)\=(.+)$/;
                                my $key = $1;
                                my $value = $2;
                                $value =~ s/^\s*//;
                                $value =~ s/\s*$//;
                                $value =~ s/\s{2,}/ /g;
                                $config{$key} = $value;

        		}
    		}
    		close(RESULTFILE);
    		my @array1 = split(",",$config{'LEVELS'});
    		$config{'LEVELS'} = \@array1;
    		my @array2 = split(",",$config{'PARAMS'});
    		$config{'PARAMS'} = \@array2;
    		my @array3 = split(" ",$config{'FCST_HOURS'});
    		$config{'FCST_HOURS'} = \@array3;
    		my @array4 = split(" ",$config{'FTP'});
    		$config{'FTP'} = \@array4;
#following print statement will dump contents of the hash, may be useful for trouble shooting future problems
#      		print Dumper(\%config);
		return \%config;
}

#-----------------------------
# Get Date - Returns the date/time formatted
#-----------------------------
sub get_date()
{
	undef @t;

        @t = gmtime(time);
        $date = "GMT " . ($t[4]+1) . "/$t[3]/" . sprintf("%02d",($t[5]-100)) . " $t[2]:$t[1]:$t[0]";

        return $date;
}

############################################################################
##  Call Tivoli with errors that prohibit the script from running correctly.
#sub call_tivoli
#{
        #Must define locally so able to send Tivoil if config file not found
#	my $kumpsend="/usr/local/bin/kumpsend";

	#---------------------------------------------------------
	# This kumpsend call uses the IFS "wasync overview 1023.ppt"
	#---------------------------------------------------------

#	local($status,$contact,$channel,$problem,$cause,$action) = @_;

#	$message = $channel. "\nCONTACT INFO:" .$contact .
#	           "\nCALLING SCRIPT: GFSGAPS " .
#	           "\nEVENT SUMMARY:" . $problem .
#				  "\nPOSSIBLE CAUSE:". $cause .
#				  "\nACTIONS REQUIRED:" . $action;
#       	print "$kumpsend cat=$status msg=\"$message\"\n";
#        if ( -x $kumpsend)
#	{
#	   @message=`$kumpsend cat=$status msg=\"$message\" 2>&1`;
#	   print "kumpsend response=";
#	   print @message;
#	}
#	else
#	{
#	   print "\nERROR: $kumpsend not found, not an executable or some other major issue!\n";
#	}
#}

