#!/usr/bin/perl -w
#
# Name:         $OPTHOME/optbin/download-3
# Purpose:      part of JGOFS data download package
#		get user to confirm options selected so far
#				  C Chandler Dec 98
#

$version = "download-3  version 3.4  11 Aug 2016";

# 11 Aug 16 WJS
#	Die if user asked for "split by levels" but did not supply any split info
# 15 Jul 15 WJS
#	In case of a "split by levels", user gets files whose names are var#valueN-of-var.  Allow
#	user to choose character other than # (per RCG request)
#  2 Dec 12	WJS
#	Bug fix: user was incorrectly forced to pick a "split by levels" variable at each level
#	Check "split by levels" variables for legal chars
#  3 Feb 12	WJS
#	Make available features like compression depend on build-env env
#    vars.  download-3's mod is to deal w/missing MAIL_SENDER, and also to
#    honor gzip compression
# 27 Dec 11	WJS
#	download-2 writes a key value sometimes, expecting download-3 to know
#    what it is.  Get that key value from download-2.  (Motivation for this
#    was that we didn't particularly LIKE what we were getting, so while changing
#    the value, improve the coordination)
#	download-2 passed a confusing parameter called  $maxlev  that wasn't actually
#    needed.  Re-create its meanings from the other info it duplicated (or so I intend!)
#	Reduce number of global variables & restructure some stuff (general principles)
#	  [begin v 3.3]

#  7 Feb 10	WJS
#	Put infoserver, dirserver & urlobjx values into form for download-3
#	While at it, check input from build-opt-env, and do general checks
#    on form vars
# 27 Jan 10	WJS
#	Mods to text related to 14 Jan mod (and some not related) from Cyndy
# 20 Jan 10	WJS
#	Mods to text related to 14 Jan mod per Tobias suggestion
# 14 Jan 10	WJS
#	Let user spec file extension for files within package
#     per Cyndy/Dicky request via Tobias.  Accordingly, have this
#     routine supply .matlab and .netcdf when appropriate, too.
#	Check legality of bulk form var
#	  [begin v 3.2]
#  1 Nov 08	WJS
#	Parametrize tracefile but leave it as STDERR
#	Use parse_object_spec to determine objnameonly
#	  [begin v 3.1]
#  8 Aug 08	WJS
#	Add blank to exported list_options.  Apparently lost in 10 May work
#	Avoid an uninitialized variable
#	  [begin download-3 v 3.0a]
# 10 May 08	WJS
#	Log with $version rather than script name
#	Process user-specified missing value string.  Unfortunately,
#     this means we have to validate it.  If there's an error, we don't
#     have download-4's presumably nice uh-oh routine or download-2's
#     presumably nice we_have_a_problem routine.  Rather than
#     duplicate them here, use quit from utilities.pl.  This requires a
#     version string, so put one in.  1 version for Cyndy, 1 for work up
#     until now means this is v 3
#	Hook to some help for deferred pickup
# 30 Aug 07	WJS
#	Remove some code duplicated in utilities.pl
#	This means we have to USE utilities.pl in the first place, of course
# 23 Dec 04	WJS
#	Avoid an uninitialized variable
# 17 Dec 04	WJS
#	Assume all download programs execute build-opt-env.pl
#    This allows removal of template & reduction in # hidden vars
#	Hardcode perl location (part of template removal)
# 	Ask for email address for deferred download
#	Remove old comments to download-X_tmp.comments
#
# =====================================================================

require "cgi-lib.pl";
require "wjs_web_perl_utilities.pl";

MAIN:
{
  $tracefile = "STDERR";

  print $tracefile " DWNLD: using script: $version \n";

  $build_opt_env = "./build-opt-env.pl";
  $! = 0;
  &check_r_access($build_opt_env);
  require "$build_opt_env";
  
  # color palette
  $credhi = "indianred";
  $chdrbar1 = "skyblue";
  $cgobar = "mediumaquamarine";
  
#
# These variables set by opt-build-env.pl via build-opt-env.pl
#
#   CGI script location
  $jgscdir   = &check_build_opt_env_var("JGSCRIPTDIR",$build_opt_env);
#   web images
  $webimages = &check_build_opt_env_var("BUTTONIMAGESDIR",$build_opt_env);
#   URL for web help docs
  $helpaddr  = &check_build_opt_env_var("HELPADDR",$build_opt_env);
#
# Read in all the variables set by the form
#
  &ReadParse(*form_info);
  
#   Get some information from input string
  $dobject = &get_form_var('dobject','REQ','OBJSPEC');
  $dobjext = &get_form_var('dobjext','REQ','OBJSPEC');	# jgofs object string with extension
  $dispobj = &get_form_var('dispobj','REQ','OBJSPEC');	# jgofs object+(QS) for display
  $subsels = &get_form_var('subsels','OPT','NOCHECK');
  $subsdisp = &get_form_var('subsdisp','OPT','NOCHECK');

  $format = &get_form_var('format','REQ');
  $bulk = &get_form_var('bulk','REQ');
  $compress = &get_form_var('compress','REQ');
  $list_options = "";
  ($format eq 'text') &&
	( ($list_options,$description_list_options) = 
			&get_list_options(&get_form_var('opt_sep','REQ'),
					  &get_form_var('opt_brief','REQ'),
					  &get_form_var('missingstring','OPT'),
					  &get_form_var('custommissing','OPT')
					 )
	);
  ($status,$errmsg,undef,$objnameonly,undef) = &parse_object_spec($dobject);
  ($status eq "OK") || 
	&quit ("Problem parsing obj spec $dobject",
		"Problem = $errmsg");

#   Print the header
  print &PrintHeader;
  
  if ($bulk eq "onebig") {
    $pkgtype="one single file";
  } elsif ($bulk eq "moresmall") {
    $pkgtype="multiple small files";
  } else {
    &quit ("Illegal value ($bulk) received for form variable bulk");
  }
      
  print $tracefile " DWNLD: working on object: $dobject \n";

#   What file extension will be appended onto filename
  $fullext = &fileext_for_packagefile($compress); 

#   Prompt user with options selected so far:
  print <<ENDOFTEXT;
   <BODY BGCOLOR="#FBFBFF">
   <h1>Data download continuing ...</h1>
   <b>Current object is:  $dispobj</b></br>
   <hr noshade><p>
  <TABLE WIDTH=100% BORDER=0 CELLSPACING=0 CELLPADDING=6>
  <TR><TD COLSPAN=3 BGCOLOR="$chdrbar1">
    <H3>You have requested:
  </TR></H3></TABLE>
        
  <UL>
  <LI><FONT color="$credhi">$pkgtype</FONT> for $objnameonly data<BR>
  <LI>Packaged as a <FONT color="$credhi">$fullext</FONT> file<BR>
  <LI>Data files will be in <FONT color="$credhi">$format</FONT> format<BR>
ENDOFTEXT

  $subsels && print "<LI>subselection list is: $subsdisp<BR> \n";
  ($format eq "text") && 
	  print "<LI>Special formatting: $description_list_options <BR> \n";

#
#   List parameters from user-selected level determinants
#     returns % separated string of selected parameters (paramstr)
#   If user hasn't selected any parameters, then force them to go back and do so
#   paramstr="" (empty string) in the case of  $bulk = onebigfile 
  $paramstr = "";
  if ($bulk eq "moresmall") {
    $no_pick_key = &get_form_var('no_pick_key','REQ');
    ($paramstr = &list_selected_params($no_pick_key)) || &go_back;
  }

#   endtags for any lists still open (just to be safe)
  print "<\/UL><\/UL><\/DL>  \n"; 

  print "<form method=\"post\" action=\"$jgscdir\/download-4\"> \n";

#   Value of # is historic.  If parametrized, it was parametrized in download4 (I think).
#   Now it's parametrized here and passed to download3.  Possibly it should be moved back
#   to download-1, so that whole package can be configured in one place ...
#   The whole purpose of choose_sep_char is to allow a user to replace said #
  $default_sep_char = '#';
  print qq|<input type="hidden" name="defvarvalsep" value="$default_sep_char">|;

#   Allow user to change the separator character in the downloaded files that result
#   from a "divide on values of variable" choice
  ($bulk eq "moresmall") && &choose_sep_char($paramstr);

#   Offer option to name packaged data file
  &name_datapkgfile($paramstr);

#   Set file extensions on each packaged file
#   Fixed for matlab, netcdf, etc - option for text
  &fileext_for_datafiles();

#   Get email address for deferred download
#   download-4 does not require a value for this, so no need to deal w/
#     missing MAIL_SENDER env var
  $ENV{"MAIL_SENDER"} && &get_email();

#   Prompt for user confirmation of selections
  &ask_user_to_confirm($paramstr); 

#
# Close the document cleanly.
#
  print &HtmlBot;

#   $dobjext defined as part of general "get build-opt-env.pl stuff in
#   here", but not used.  undef here to repress diagnostic, while
#   allowing future use if needed.
  undef $dobjext;
}


sub fileext_for_packagefile 
# Determine which package type user has selected (zip, tar, etc.):
{
  my ($compress) = @_;
  
  if ($compress eq "targz") {
    $fullext = "tar.gz";
  } elsif ($compress eq "tarZ") {
    $fullext = "tar.Z";
  } else {
    $fullext = $compress;
  }
  return $fullext;
}


sub get_list_options 
{
  my ($separation,$headers,$default_missing,$user_missing) = @_;
  my ($list_options,$missing_value_string,$description);

#   We force list output to be nonstop, flat file, no comments (-n -f/-b -c)
#   (-n should not be needed w/list 1.7, which is semi-required to
#   avoid issues w/attribute lists.  However, we'll leave it in)
  $list_options = "-n -c";

  if ($separation eq "SPACESEP") {
    $list_options .= " -s";
    $description = "space-separated, data aligned in columns";
  } elsif ($separation eq "TABSEP") {
    $list_options .= " -t";
    $description = "tab-separated, data aligned in columns";
  } elsif ($separation eq "DEFAULT") {
    $description = "comma-separated, data aligned in columns";
  } elsif ($separation eq "SUPPRESS_SPACES") {
    $list_options .= " -z";
    $description = "comma-separated, not aligned in columns";
  } else {
    &quit ("Invalid data separation/alignment option $separation");
  }

  if ($headers eq "NOHEADERS") {
    $list_options .= " -b";
    $description .= ", no header info";
  } elsif ($headers eq "FLAT") {
    $list_options .= " -f";
  } else {
    &quit ("Invalid header option $headers");
  }

  $missing_value_string = $user_missing;
  ((defined $missing_value_string) && ($missing_value_string ne "")) ||
	($missing_value_string = $default_missing);
  if ($missing_value_string ne 'nd') {
    ($missing_value_string =~ /^[\w\-\+\.]+$/) || 
      &quit ("Missing value string limited to letters, underscores, " .
		"digits, decimal points, and pluses and minuses",
	      "Cannot use missing value string  ==>$missing_value_string<==");
    $list_options .= q^ -m "$missing_value_string"^;
    $description .= ", missing values converted to $missing_value_string";
  }

#   BE SURE $list_options leaves here w/leading & trailing blanks
#   The programs that put it on a command line don't seem to be responsible
#   enough to do it themselves.  We used to do it here, and it's easier
#   to continue than to track down all the others.
  return " $list_options ",$description;
}


sub list_selected_params {
#
# Build list of parameters from user-selected level determinants
#
  my ($no_pick_key,$dummy) = @_;
  my ($levelparams,$num,$deternum,$determinant);

  ($no_pick_key && (! $dummy)) || 
    &quit ("Internal error: list_selected_params received wrong # args (or empty args)");

  print "<LI>Determined by the following parameter(s)<BR><DL>\n";     
  
  $levelparams = "";
  $num = 0;
  $determnum = "determine" . $num;
  while (  $determinant = &get_form_var($determnum,'OPT','SPACEOK')  ) {
#     if user did not make a pick at this level, 
#       decrement maxlev and shuffle params [? to both actions for now. WJS Dec 11]
#     if user DID make a pick, add it to levelparams, the final selection parameter list
    if ( $determinant eq $no_pick_key) {
      print "[ no parameter selected at level $num ] <BR>\n";
    } else {
      ($determinant =~ /^[a-z0-9A-Z_]+$/) || 
	&quit ("Illegal character in varname used for level selection.  ",
	       "Legal chars letters, digits, underscores.  Problem string: $determinant");
      print "<DT><FONT color=\"$credhi\">$determinant</FONT> &nbsp;&nbsp;&nbsp; [at level $num]<BR>\n";
      $levelparams .= "%"."$determinant";
    }
    $determnum = "determine" . ++$num ;
  }
#
# remove leading % character from final list of parameters
# Calling program handles situation where $levelparams is empty
#
  $levelparams =~ s/^%//;
  
  return $levelparams;
}


sub get_email
{
  print <<ENDOFSUB;

 <TABLE WIDTH=100% BORDER=0 CELLSPACING=0 CELLPADDING=6>
 <TR><TD COLSPAN=3 BGCOLOR="$chdrbar1">
   <H3>Would you like to get email when your download is done?
      <TD BGCOLOR="$chdrbar1">
        <A HREF="$helpaddr/download-help.html#deferred"><img alt="[HELP]" 
        align=absmiddle border=0 src="$webimages/helpbutton.gif"></A></TD>
 </TR></H3></TABLE>
 <P> 
  If your download takes a long time, you can go away and come
  back for it later.  If you'd like to get email when the download request
  is complete, enter your email address below
  <dt><dd><B>email address</B> &nbsp
  <input name="email"><p>
  </dl></dl><p>
ENDOFSUB
}

sub name_datapkgfile {
   my ($paramlist) = @_;
#
# Present user with option to name packaged data file ($pkgname)
# default is object name from $dobject, but might also be a selected 
# param/determinant offer drop down list of whatever I know about the selections
#
# This has to be inside a FORM tag
#
  print <<ENDOFTEXT;
  <TABLE WIDTH=100% BORDER=0 CELLSPACING=0 CELLPADDING=6>
  <TR><TD COLSPAN=3 BGCOLOR="$chdrbar1">
    <H3>What would you like to name the package of files?</TD>
    <TD BGCOLOR="$chdrbar1">
      <A HREF="$helpaddr/download-help.html#pkgname"><img alt="[HELP]" 
      align=absmiddle border=0 src="$webimages/helpbutton.gif"></A></TD>
  </TR></H3></TABLE>
  <P> 
  The selected 'name' will be used in naming the final package of data files.
  For example, the default is to name the file according to the selected 
  object, <FONT COLOR="$credhi">$objnameonly</FONT>,  
  which has been preselected from the drop-down list below.
  In this case the resultant file would be named: 
  <B><FONT COLOR="$credhi">$objnameonly</FONT>.</B><FONT COLOR="$credhi">$fullext</FONT><BR>
  Notice, the appropriate file extension 
  (<FONT COLOR="$credhi">$fullext</FONT>) has been appended to 'name'.  
  <dl>
  <dt><dd><B>Choose a name for your file package: </B> &nbsp
  <select name="pkgname">
  <option value="$objnameonly" selected> $objnameonly
ENDOFTEXT

  foreach $param (split(/%/,$paramlist)) {
    print "<option value=\"$param\"> $param \n";
  }
  
print <<ENDOFTEXT;  
  </select>
  <dt><dd><B>or type another name in this box</B> &nbsp
  <input name="customname"><p>
  </dl></dl><p>
ENDOFTEXT
}

sub choose_sep_char {
  my (@split_vars,$lowest_level_split_var,$example_string);
  my ($level_params,$dummy) = @_;
  (   $level_params   &&   ( ! (defined $dummy))   ) || 
        &quit ("Internal error: Bad args to choose_sep_char");
#
# Guts of routine gets a character from the user.  Fun part is trying to describe what
# the character represents.  Serious issue is what character(s) to allow the user to choose
# since the chosen character ends up in filenames, followed by data values from JGOFS object
# Consider a JGOFS datum of 'rm *' preceded by a user-chosen semicolon.  Anything that uses
# that filename in a "string to the shell" is open to problems
#
# This has to be inside a FORM tag
#
#   % hardcoded elsewhere.  Parametrize? why spoil the fun?
  @split_vars = split '%',$level_params;
  $lowest_level_split_var = pop @split_vars;
  $example_string = $lowest_level_split_var . $default_sep_char ."a-value-of-" . $lowest_level_split_var;
  print <<ENDOFTEXT;
  <TABLE WIDTH=100% BORDER=0 CELLSPACING=0 CELLPADDING=6>
  <TR><TD COLSPAN=3 BGCOLOR="$chdrbar1">
    <H3>Within the names of the downloaded files, what separator character would you like?</TD>
    <TD BGCOLOR="$chdrbar1">
      <A HREF="$helpaddr/download-help.html#varvalsepchar"><img alt="[HELP]" 
      align=absmiddle border=0 src="$webimages/helpbutton.gif"></A></TD>
  </TR></H3></TABLE>
  <P> 
  Each of the multiple small files will have a name of the form 
  <FONT COLOR="$credhi">$example_string</FONT>
  If you wish, you can choose a character instead of the $default_sep_char;
  <dl>
  <dt><dd><B>Type it in this box</B> &nbsp
  <input name="varvalsepchar"><p>
  </dl></dl><p>
ENDOFTEXT
}


sub fileext_for_datafiles {

  ($format =~ /^matlab/) && ($file_ext = "mat");
  ($format eq "netcdf") && ($file_ext = "netcdf");
  if (defined $file_ext) {
    print qq|<input type="hidden" name="datafile_ext" value="$file_ext">|;
    print qq|<input type="hidden" name="custom_datafile_ext" value="">|;
    return;
  }

  my ($singular_plural,$separation);
#
# Present user with option to provide an extent for the data files 
# ($datafile_ext)
# Defaults are empty for multiple file downloads and format-dependent
# for "one big file" downloads
#
# This has to be inside a FORM tag
#
  $singular_plural = ($bulk eq "onebig") ? 
		"name of that file" : "names of each of those files";
  $singular_plural2 = ($bulk eq "onebig") ? 
		"" : "s";
  $singular_plural3 = ($bulk eq "onebig") ? 
		"" : "filenames of the form ";
  print <<ENDOFTEXT;
  <TABLE WIDTH=100% BORDER=0 CELLSPACING=0 CELLPADDING=6>
  <TR>
  <TD COLSPAN=3 BGCOLOR="$chdrbar1">
    <H3>What extension would you like to add to the datafile$singular_plural2?
  </TD>
    <TD BGCOLOR="$chdrbar1">
      <A HREF="$helpaddr/download-help.html#datafile_ext"><img alt="[HELP]" 
      align=absmiddle border=0 src="$webimages/helpbutton.gif"></A></TD>
  </TR></H3></TABLE>
  <P> 
  After you unpack the package file you named above, your selected data will
  be in $pkgtype.  In this section, you can provide a string to be appended
  to the $singular_plural.  If you provide a non-empty string, we will
  put a "." in front of it.  For example, if you give us txt, your selected
  data will be in $singular_plural3 name.txt
  <dl>
  <dt><dd><B>Choose an extension for your packaged files: </B> &nbsp
  <select name="datafile_ext">
ENDOFTEXT

  $separation = &get_form_var('opt_sep','REQ');
  &print_select_item("EMPTY_FILE_EXTENT",
		     ($bulk eq "moresmall"),
		     "Do not add anything, please"
		    );
  &print_select_item("txt",
		     (  ($bulk eq "onebig") && ($separation eq "SPACESEP")  )
		    );
  &print_select_item("tsv",
		     (  ($bulk eq "onebig") && ($separation eq "TABSEP")  )
		    );
  $csv = (($separation eq "DEFAULT") || ($separation eq "SUPPRESS_SPACES"));
  &print_select_item("csv",
		     (  ($bulk eq "onebig") && $csv  )
		    );
  &print_select_item("dat",0);
  &print_select_item("all",0);
  
print <<ENDOFTEXT;  
  </select>
  <dt><dd><B>or type another extension in this box</B> &nbsp
  <input name="custom_datafile_ext"><p>
  </dl></dl><p>
ENDOFTEXT
}

sub ask_user_to_confirm {
#
# Ask user to confirm selections so far
#
  print <<ENDOFSUB;

 <TABLE WIDTH=100% BORDER=0 CELLSPACING=0 CELLPADDING=6>
 <TR><TD COLSPAN=3 BGCOLOR="$chdrbar1">
   <H3>Are you satisfied with these selections?
 </TR></H3></TABLE>
 
 <input type="hidden" name="levelparams" value="$paramstr">
 <input type="hidden" name="bulk" value="$form_info{'bulk'}">
 <input type="hidden" name="dobject" value="$form_info{'dobject'}">
 <input type="hidden" name="dobjext" value="$form_info{'dobjext'}">
 <input type="hidden" name="urlobjx" value="$form_info{'urlobjx'}">
 <input type="hidden" name="dispobj" value="$dispobj">
 <input type="hidden" name="dobj_dirserver" value="$form_info{'dobj_dirserver'}">
 <input type="hidden" name="dobj_infoserver" value="$form_info{'dobj_infoserver'}">
 <input type="hidden" name="compress" value="$form_info{'compress'}">
 <input type="hidden" name="subsels" value="$subsels">
 <input type="hidden" name="subsdisp" value="$form_info{'subsdisp'}">
 <input type="hidden" name="list_options" value="$list_options">
 <input type="hidden" name="format" value="$form_info{'format'}">
 <TABLE BORDER=0 CELLSPACING=20 CELLPADDING=0>
 <TR>
  <TD WIDTH="100">
    <B><input type="submit" width="80" style="background:$cgobar" 
			name="confirm" value="yes"></B></TD>
  <TD WIDTH="290">
    <B><input type="submit" width="80" style="background:$credhi" 
			name="confirm" value="no">
		</B><FONT COLOR="$credhi">  Go back and try again.</FONT></TD>
  <TD WIDTH="210">
    <B><input type="submit" width="80" 
		style="background:blue;color:white" ="white" 
			name="confirm" value="help">
		</B><FONT COLOR="blue">  me please!</FONT></TD>
  </B></TR></TABLE>
 </form>

ENDOFSUB
}


sub go_back {
   # Need to redirect user if they requested multi file output, 
   # but neglected to select any params by which we can divide data
   # var defined on next line not used as of May '04.  Comment it out
   # $previous_page=$ENV{'HTTP_REFERER'};
   #print <<ENDOFBACK;
   #</UL></UL></DL>
   #<HR NOSHADE WIDTH="100%"> 
   #<H3>
   #You have not selected any parameters which can be used to subdivide 
   #your data. Please use your browser's 'Back button' to go back
   #and select at least one parameter.</H3><p>  
   #<HR SIZE=4 NOSHADE WIDTH="100%"><br>   
   #   
#ENDOFBACK
  &quit("You have not selected any parameters which can be used to subdivide " .
   "your data. Please use your browser's 'Back button' to go back " .
   "and select at least one parameter.")
}

sub print_select_item
{
  my ($optval,$selected,$label) = @_;

  $label || ($label = $optval);

  print "<option";
  $selected && (print " selected");
  print qq| value="$optval"> $label\n|;

  return;
}
