#!/usr/bin/env perl
##########################################################################
#
# routine: merge_split.pl
#
# purpose: Merges q/s split observations.  Identifies the q/s split
#          pair using the triggering OSF.  Determines the order of the
#          split pair using the DCF numbers of the OSFs.  
#          Concatenates the binary and ASCII data files of the
#          lower and higher observations together in a work area.
#          When all concatenations are complete, the new files
#          are copied back into the pipeline directory, overwriting
#          the existing files for the "higher" observation.
#          The OSF for the higher observation is then triggered to
#          move down the pipeline, while the files and OSF for the
#          lower observation remain present.  They will be cleaned
#          once the repaired observation completes processing.
#          In OTFR, they are cleaned automatically.
#
# modification history:
#
#   date    opr     who     reason
# -------- -----  --------  --------------------------------------
# 10/05/00 42246  MSwam     first version
# 04/09/02 44603  MSwam     remove check for .erx diffs
# 08/11/05 53803  MSwam     Replace PATH_FILE_NAME with PATH_BASENAME
# 10/05/07 57570  MSwam     Replace DCFNUM check with pktTime check for order
# 09/19/09 xxxxx  MSwam     Add byte offset handling for ULI, like PKI
# 
##########################################################################
#
# prepend the Perl include variable using all components of PATH
# (this allows us to reuse other OTFR Perl code)
#
$PATH  = $ENV{"PATH"};
@parts = split /:/, $PATH;
while (defined($val = pop(@parts))) {
   if (substr($val,0,1) eq "/") { unshift(@INC, $val)}
}

#
# include these modules
#
require 'printmsg.pl';       # prints a formatted status message
require 'resolve.pl';        # resolve stretches 

# set-up 
#
$all_is_well = 0;
$quit_this_dataset = 1;
$go_absent = 102;

$path     = $ENV{"PATH_BASENAME"};
$SIS_DIR  = Resolve("SIS_DIR");
$OSF_DATASET = $ENV{"OSF_DATASET"};
$OPUS_TEMP_DIR = $ENV{"OPUS_TEMP_DIR"};
$RESOURCE_FILE = $ENV{"RESOURCE_FILE"};
$RESOURCE_ITEM = $ENV{"RESOURCE_ITEM"};

#
# find the pair of exposures
$searchval = substr($OSF_DATASET,0,8);
@out = `osf_test -p $path -f $searchval\? -pr dataset`;
$savestat = $?;
if ($savestat != 0) {
   PrintMsg("E","ERROR: osf_test failed for $path,$searchval; ecode= $savestat\n");
   exit $quit_this_dataset;
}
if (scalar(@out) != 2) {
   PrintMsg("E","ERROR: osf_test did not find 2 OSFs for $path,$searchval\n");
   PrintMsg("E","@out");
   exit $quit_this_dataset;
}
print @out;
$dset1 = substr($out[0],0,9);
$dset2 = substr($out[1],0,9);

# grab pktTime fields of each file's first line and compare to see which
# is the "lower" file
#
$file1_line = `head -1 $SIS_DIR$dset1.pki`;
$file2_line = `head -1 $SIS_DIR$dset2.pki`;
($dontcare1, $dontcare2, $dontcare3, $file1_timefield) = split /\s+/,$file1_line;
($dontcare1, $dontcare2, $dontcare3, $file2_timefield) = split /\s+/,$file2_line;
# convert to decimal 
$file1_timefield += 0.0;
$file2_timefield += 0.0;
PrintMsg("I","Times check for ordering $dset1: $file1_timefield, $dset2: $file2_timefield\n");

if ($file1_timefield < $file2_timefield) {
  $lower = $dset1;
  $higher = $dset2;
}
else {
  $lower = $dset2;
  $higher = $dset1;
}

# concatenate PKX files using HST-specific catfiles
`catfiles $SIS_DIR$lower.pkx $SIS_DIR$higher.pkx -o $OPUS_TEMP_DIR/$higher.pkx`;
if ($? != 0) {
   PrintMsg("E","ERROR: catfiles failed for $SIS_DIR$lower.pkx,$SIS_DIR$higher.pkx\n");
   exit $quit_this_dataset;
}

# copy lower PKI file to temp area and name it as the higher PKI
use File::Copy;
if (!copy("${SIS_DIR}${lower}.pki", "${OPUS_TEMP_DIR}/${higher}.pki")) {
    PrintMsg("E","ERROR: copy from $SIS_DIR$lower.pki to $OPUS_TEMP_DIR/$higher.pki failed; (error=$!).\n");
    exit $quit_this_dataset;
}

# determine initial byte offset for the rest of the new PKI file
# by using the last known byte offset of the lower PKI file
# (found between the last two lines of the lower file)
@last = `tail -2 $SIS_DIR/$lower.pki`;
#
# trim leading whitespace
$last[0] =~ s/^\s+//g;
$last[1] =~ s/^\s+//g;
#
# parse on remaining whitespace
($dontcare1, $dontcare2, $dontcare3, $near_last_offset) = split /\s+/,$last[0];  
($dontcare1, $dontcare2, $dontcare3, $last_offset) = split /\s+/,$last[1];  
chomp($near_last_offset);
chomp($last_offset);

$increment = $last_offset + 0 - $near_last_offset;
$full_lower_offset = $last_offset + $increment;
PrintMsg("I","PKI offsets,incr: $near_last_offset,$last_offset,$increment: $full_lower_offset");

# append higher PKI file to temp area PKI (lower PKI), adjusting each byte offset
if (!open(HIGHER, "$SIS_DIR$higher.pki")) {   # for reading
   PrintMsg("E","ERROR: failed to open $SIS_DIR$higher.pki\n"); 
   exit $quit_this_dataset;
}
if (!open(TEMP_HIGHER, ">>$OPUS_TEMP_DIR$higher.pki")) {  # for appending
   PrintMsg("E","ERROR: failed to open $OPUS_TEMP_DIR$higher.pki\n"); 
   exit $quit_this_dataset;
}
while (<HIGHER>) {
   # split the read buffer ($_) into fields on whitespace, after skipping leading space
   ($frame, $line, $timestamp, $old_offset) = split;
   chomp($old_offset);
   # compute the new byte offset, using the offset of the entire lower file
   $new_offset = $old_offset + 0 + $full_lower_offset;
   print TEMP_HIGHER " $frame $line  $timestamp $new_offset\n";
}
close(HIGHER);
close(TEMP_HIGHER);

# append lower and higher trailer files together
`cat $SIS_DIR$lower.trx $SIS_DIR$higher.trx > $OPUS_TEMP_DIR$higher.trx`;
if ($? != 0) {
   PrintMsg("E","ERROR: Concatenation of TRX files failed for $SIS_DIR$lower,$SIS_DIR$higher\n");
   exit $quit_this_dataset;
}

# combine ULX files
`catfiles $SIS_DIR$lower.ulx $SIS_DIR$higher.ulx -o $OPUS_TEMP_DIR/$higher.ulx`;
if ($? != 0) {
   PrintMsg("E","ERROR: catfiles failed for $SIS_DIR$lower.ulx,$SIS_DIR$higher.ulx\n");
   exit $quit_this_dataset;
}

# copy lower ULI file to temp area and name it as the higher ULI
use File::Copy;
if (!copy("${SIS_DIR}${lower}.uli", "${OPUS_TEMP_DIR}/${higher}.uli")) {
    PrintMsg("E","ERROR: copy from $SIS_DIR$lower.uli to $OPUS_TEMP_DIR/$higher.uli failed; (error=$!).\n");
    exit $quit_this_dataset;
}

# determine initial byte offset for the rest of the new ULI file
# and use the same increment found for the PKI file
@last = `tail -1 $SIS_DIR/$lower.uli`;
#
# trim leading whitespace
$last[0] =~ s/^\s+//g;
#
# parse on remaining whitespace
($dontcare1, $dontcare2, $dontcare3, $last_offset) = split /\s+/,$last[0];  
chomp($last_offset);

$full_lower_offset = $last_offset + $increment;
PrintMsg("I","ULI offsets,incr: $last_offset,$increment: $full_lower_offset");

# append higher ULI file to temp area ULI (lower ULI), adjusting each byte offset
if (!open(HIGHER, "$SIS_DIR$higher.uli")) {   # for reading
   PrintMsg("E","ERROR: failed to open $SIS_DIR$higher.uli\n"); 
   exit $quit_this_dataset;
}
if (!open(TEMP_HIGHER, ">>$OPUS_TEMP_DIR$higher.uli")) {  # for appending
   PrintMsg("E","ERROR: failed to open $OPUS_TEMP_DIR$higher.uli\n"); 
   exit $quit_this_dataset;
}
while (<HIGHER>) {
   # split the read buffer ($_) into fields on whitespace, after skipping leading space
   ($frame, $line, $timestamp, $old_offset) = split;
   chomp($old_offset);
   # compute the new byte offset, using the offset of the entire lower file
   $new_offset = $old_offset + 0 + $full_lower_offset;
   print TEMP_HIGHER " $frame $line  $timestamp $new_offset\n";
}
close(HIGHER);
close(TEMP_HIGHER);

# move combined files from temp area back into the pipeline directory
# (these will overwrite the existing HIGHER files)
$fileset_mask = "$OPUS_TEMP_DIR/$higher\*";
@fileset = glob($fileset_mask);
if (! scalar(@fileset)) {
    PrintMsg("E","ERROR: Unable to move new files; No files located using $fileset_mask\n");
    exit $quit_this_dataset;
}
PrintMsg("I","moving new files $fileset_mask back to pipeline $SIS_DIR/");
`mv $fileset_mask $SIS_DIR/`;
if ($? != 0) {
    # move failed
    PrintMsg("E","ERROR: rename of $fileset_mask failed ($!)\n");
    exit $quit_this_dataset;
}

# update OSF for HIGHER to push it past Data Partitioning
`osf_update -p $path -f $higher -r OPUS_DEFINITIONS_DIR:${RESOURCE_FILE}.resource -y $RESOURCE_ITEM`;
if ($? != 0) {
    PrintMsg("E","ERROR: failed to update OSF for $path,$higher to $RESOURCE_FILE:$RESOURCE_ITEM\n");
    exit $quit_this_dataset;
}
PrintMsg("I","updated OSF for $higher using $RESOURCE_FILE.$RESOURCE_ITEM");

exit $all_is_well;
