#!/usr/bin/perl
use FileHandle;
use File::Basename;
use Getopt::Long;

$sflag = 0;
$sc = 0.8;
$exp = .35;
$exp2 = 1;
$rsc = 1.0;

#command line options parsing, the rest of the arguments are passed to @ARGV
GetOptions ('s=f' => \$rsc);

if (($#ARGV + 1) < 4){die <<EOS ;}
*** Copyright 2015, Gamma Remote Sensing, v2.9 19-Jun-2015 clw ***
*** Calculate MLI images for a stack of SLCs and average ***

usage: $0 <SLC_tab> <MLI_dir> <rlks> <azlks> [sflag] [scale] [exp] [MLI_ave] 

    SLC_tab     (input) two column list of SLC filenames and SLC parameter filenames (including paths) (ascii)
    MLI_dir     directory to contain MLI images and MLI image parameter files
    rlks        range looks for the MLI images
    azlks       azimuth looks for the MLI images
    sflag       MLI image average flag:
                  0: no   (default)
                  1: yes 
    scale       relative intensity display scale factor (default: $sc)
    exp         display exponent (default: $exp)
    MLI_ave     MLI average image filename (without path)
    -s scale    MLI radiometric scale factor, nominal value for calibrated SCOMPLEX HH and VV data: 1.e-6

    NOTE: The current directory is denoted using . 
EOS

$mli_dir = $ARGV[1];
$rlks    = $ARGV[2];
$azlks   = $ARGV[3];
$log = "$mli_dir/mk_mli_all.log";
print "MLI data directory: $mli_dir\n";

unless (-d $mli_dir) {
  $exit = system("mkdir -p $mli_dir");
  $exit == 0 or die "ERROR execute: non-zero exit status: mkdir $mli_dir\n"
}

$time = localtime;
print "*** $0 processing start: $time ***\n";
print "log file: $log\n"; 

open(LOG,">$log") or die "ERROR $0: cannot open log file: $log\n\n";
LOG->autoflush;print LOG "$0 @ARGV\n\n";	#print command line that was used
print LOG "$0 @ARGV\n\n";
print LOG "*** $0 processing start: $time ***\n";

open(SLC_TAB, "<$ARGV[0]") or die "\nERROR $0: Table of SLC images and parameter files does not exist: $ARGV[0]\n\n";
print "SLC_tab: $ARGV[0]\n"; 

if($#ARGV + 1 > 5){$sc = $ARGV[5];}
if($#ARGV + 1 > 6){$exp = $ARGV[6];} 

($sc > 0.0) or die "\nERROR $0: MLI display scale factor <= 0.0 : $sc\n";
($exp > 0.0) or die "\nERROR $0: MLI display exponent <= 0.0 : $exp\n";
  
$rlks =~ /\d+$/ && $rlks > 0 or die "ERROR $0: invalid number of range looks: $rlks\n";
$azlks  =~ /\d+$/ && $azlks > 0 or die "ERROR $0: invalid number of azimuth looks: $azlks\n";

print "MLI range looks: $rlks  azimuth looks: $azlks\n";
print "MLI display scale factor: $sc\n";
print "MLI display exponent: $exp\n";
print "MLI radiometric scale factor: $rsc\n";
print LOG "MLI range looks: $rlks  azimuth looks: $azlks\n";
print LOG "MLI display scale factor: $sc\n";
print LOG "MLI display exponent: $exp\n";
print LOG "MLI radiometric scale factor: $rsc\n";
close LOG;
$rsc >= 0.0 or die "MLI radiometric scale factor must be >= 0.0";

if(($#ARGV + 1) > 4){
  $sflag = $ARGV[4];
  if($sflag == 1){ 
    $#ARGV >= 7 or die "\nERROR: no name for the MLI_ave image provided\n";
    $mli_ave_fn = $ARGV[7];
    $mli_list = $mli_dir."/"."mli_list";
    open(MLI_LIST, ">$mli_list") or die "ERROR $0: cannot open mli_list file: $mli_list\n\n";
    $nmli = 0;
  }
}

LINE: while (<SLC_TAB>) {	#read lines of processing list file
  chomp $_;			#remove new line from record
  next LINE if /^$/;		#skip blank lines in processing list
  next LINE if /^#/;		#skip comments in processing list
  @fields = split;		#extract the scene identifier and other parameters on the line if present
  
  $slc = $fields[0];
  $slc_par = $fields[1];
  my ($s1, $dir1, $ext1) = fileparse($slc, qr/\.[^.]*/); #extension is the last bit after the last period   
  
  if($ext1 =~/rslc.*/) {$mli_ext = "rmli";}	#check if slc or rslc
  else {$mli_ext = "mli";}

  @width = extract_param($slc_par, "range_samples:");
  $mli = $mli_dir."/".$s1.".".$mli_ext;
  $mli_par = $mli.".par";
  $time = localtime;
  print "\n*** SLC: $slc  width: $width[1]  start time: $time ***\n";  

  open(LOG,">>$log") or die "ERROR $0: cannot open log file: $log\n\n";
  print LOG "\n*** SLC: $slc  width: $width[1]  start time: $time ***\n";  
  close LOG;
  
  execute("multi_look $slc $slc_par $mli $mli_par $rlks $azlks 0 - $rsc $exp2", $log);
  @width2 = extract_param($mli_par,"range_samples:");	#determine width of MLI image
  @height2 = extract_param($mli_par,"azimuth_lines:");	#number of lines in the MLI image
  execute("raspwr $mli $width2[1] 1 $height2[1] 1 1 $sc $exp", $log);
  if ($sflag == 1){
    print MLI_LIST "$mli\n";
    $nmli++;
  }	
}

$time = localtime;
if ($sflag == 1){
  close MLI_LIST;
  print "\n*** Generate multi-look sum of the MLI image stack  $time ***\n";
  open(LOG,">>$log") or die "ERROR $0: cannot open log file: $log\n\n";
  print LOG"\n*** Generate multi-look sum of the MLI image stack ***\n";
 
  $mli_ave =  $mli_dir."/".$mli_ave_fn;
  $nmli_min = int($nmli - $nmli/4);
  $nmli_min > 0 or $nmli_min = 1;

  print "list of MLI files: $mli_list\n";
  print "MLI average image: $mli_ave\n";
  print "number of MLI images: $nmli\n";
  print "minimum number of non-zero images: $nmli_min\n";
  print LOG "list of MLI files: $mli_list\n";
  print LOG "MLI average image: $mli_ave\n";
  print LOG "number of MLI images: $nmli\n";
  print LOG "minimum number of non-zero images: $nmli_min\n\n";
  close LOG;
  execute("ave_image $mli_list $width2[1] $mli_ave 1 - 1 1 0 $nmli_min", $log);
  execute("raspwr $mli_ave $width2[1] 1 0 1 1 $sc $exp", $log);
}

$time = localtime;
print "\n*** $0 processing end: $time ***\n";
open(LOG,">>$log") or die "ERROR $0: cannot open log file: $log\n\n";
print LOG "\n*** $0 processing end: $time ***\n";
exit 0;

sub execute{
  my ($command, $log) = @_;  
  if (-e $log){open(LOG,">>$log") or die "\nERROR $0: cannot open existing log file: $log\n";}
  else {open(LOG,">$log") or die "\nERROR $0: cannot open new log file: $log\n";} 
  LOG->autoflush; 
  print "$command\n";
  print LOG ("\n${command}\n");
  close LOG;  
  $exit = system("$command 1 >> $log");
  $exit == 0 or die "ERROR $0: non-zero exit status: $command\n";
}

sub extract_param{
  my ($infile,$keyword) = @_;
  open(PAR_IN,$infile) || die "\nERROR extract_param: cannot open parameter file: $infile\n";

  while(<PAR_IN>){
    chomp;
    @tokens = split;
    if($tokens[0] eq $keyword){close PAR_IN; return @tokens;}
  }
  close PAR_IN;
  die "\nERROR $0: keyword $keyword not found in file: $infile\n";
}
