#
# This TCL script modifies the values of a few common parameters
#    in all the other parameter files.  When one first unpacks
#    and installs the software, one should
#
#       1. modify the "setup.param" values to suit one's system
#       2. execute the setup routine
# 
#    Then one can run all the other routines without having to edit
#    their param files directly.
#
#       --- MWR 1/6/2001
#    
# Added "latitude" and "longitude" parameters.
#       --- MWR 1/28/2001
#
# Added code to create namespace for Directory, and to get/set directory
#     values.
#       --- MWR 2/9/2001
#
# Added code to put the SYM_TABLE value into the environment
#       --- MWR 2/9/2001
#
# Now read in and set values for "match", "photom", and "bait" directories
#       --- MWR 2/11/2001
#
# Modified sscanf line in "fix_params" so that we do NOT have to scan
#     both keyword and value in order to replace the value.  This means
#     we will be able to replace an empty value, i.e. turn this:
#          keyword
#     into this
#          keyword value
#
#       --- MWR 7/9/2001
#    
# Add "xvista_dir" to the list of items that are replaced by "setup".
#     Needs to be fixed so it will appear properly in "thumbnail.param".
#       --- MWR 5/7/2002
#
# Add procedure "check_compatibility" to verify that the user has provided
#     the proper versions of some subsidiary software
#       --- MWR 11/26/2002
#
# Moved the "check_compatibility" function out of this source code file
#     and into the "version.tcl" file.
#       --- MWR 04/22/2003
#
# Changed the single "refcat_dir" into separate "astrom_refcat_dir"
#     and "photom_refcat_dir" variables.
#       --- MWR 4/25/2003
#


if { [catch { set debug } ] == 1 } {
  set debug 2
}

source param.tcl


###########################################################################
# Look in the given param file to find keyword/value pairs.
#   Then, for all OTHER param files in the directory, 
#   look for keyword matching one in the given param file;
#   if found, replace its value with the value in the given param file
#
# Args:
#      param_file         name of file we use to replace values in other
#                            param files
#
# RETURNS
#    0           if all goes well
#    1           if there's a problem
#    
proc setup { param_file } {
  global debug

  if { $debug > 0 } {
    puts "entering setup"
  }

  # get information from the param file
  if { [file exists $param_file] != 1 } {
    puts stderr "setup: can't open param file $param_file"
    return 1
  }
  set input_dir [get_param $param_file "input_dir"]
  set output_dir [get_param $param_file "output_dir"]
  set astrom_refcat_dir [get_param $param_file "astrom_refcat_dir"]
  set photom_refcat_dir [get_param $param_file "photom_refcat_dir"]
  set xvista_dir [get_param $param_file "xvista_dir"]
  set imagelist_name [get_param $param_file "imagelist_name"]
  set latitude   [get_param $param_file "latitude"]
  set longitude  [get_param $param_file "longitude"]
  set skip_bad   [get_param $param_file "skip_bad"]

  set match_dir  [get_param $param_file "match_dir"]
  set photom_dir [get_param $param_file "photom_dir"]

  set klist " { input_dir $input_dir } \
              { output_dir $output_dir } \
	      { astrom_refcat_dir $astrom_refcat_dir } \
	      { photom_refcat_dir $photom_refcat_dir } \
	      { xvista_dir $xvista_dir } \
	      { imagelist_name $imagelist_name } \
	      { latitude   $latitude } \
	      { longitude  $longitude } \
         { skip_bad   $skip_bad } " 
  if { $debug > 1 } {
    puts "setup: klist is ..$klist.. "
    puts "length of klist is [llength $klist]"
  }


  # make up a list of all ".param" files in the current directory, but
  #   don't include the param_file given as arg to this procedure
  set other_param_files [glob *.param]
  set this_ind [lsearch $other_param_files $param_file]
  if { $this_ind == -1 } {
    # no problem -- we don't need to remove any file from the list
  } else {
    set other_param_files [lreplace $other_param_files $this_ind $this_ind]
  }
  if { $debug > 1 } {
    puts "setup: will work on these param files"
    puts $other_param_files
  }

  # now, for each file in the list, replace instances of the special
  #  keyword/value pairs
  foreach file $other_param_files {
    if { [fix_params $file $klist] != 0 } {
      puts stderr "setup: fix_params returns with error"
      return 1
    }
  }


  if { $debug > 1 } {
    puts "setup: end of setup"
  }
  

  return 0
}


#############################################################################
# PROCEDURE: fix_params
#
# DESCRIPTION: given a file name and a list of keyword/value pairs,
#              look in the file for any line with a keyword in the
#              list of pairs.  If found, replace its value with the
#              value from the list.
#
# RETURNS:
#     0               if all goes well
#     1               if not
#
proc fix_params { param_file klist } {
  global debug

  if { $debug > 2 } {
    puts "entering fix_params "
    puts "  param_file $param_file  klist $klist "
  }

  set tmp_file "fix_params.tmp"

  if { [catch { set fid [open $param_file "r"] } ] != 0 } {
    puts stderr "fix_params: can't open param file $param_file for reading"
    return 1
  }
  if { [catch { set fout [open $tmp_file "w"] } ] != 0 } {
    puts stderr "fix_params: can't open temp file $tmp_file for writing"
    return 1
  }

  # now, check each line from param file.  If matches a keyword,
  #   replace value.  Place each (possibly modified) line into
  #   the temporary file.
  while { [gets $fid line] != -1 } {
    
    if { [scan $line "%s" key] != 1 } {
      puts $fout $line
      continue
    }

    set replaced_it 0
    foreach elem $klist {
      set elem_key [lindex $elem 0]
      set elem_val [lindex $elem 1]
      if { [string compare $key $elem_key] == 0 } {
	# replace with our key from the klist
        puts $fout [format "%s    %s" $elem_key $elem_val]
	set replaced_it 1

      } else {
        # nope, doesn't match
      }

      if { $replaced_it == 1 } {
        break
      }
    }

    # if we didn't replace the line, then copy the original to the 
    #   temporary copy
    if { $replaced_it == 0 } {
      puts $fout $line
    }

  }

  close $fid
  close $fout

  # now, replace the original file with the (possibly modified) copy
  exec mv $tmp_file $param_file

  return 0
}



#############################################################################
# PROCEDURE: set_sym_table
#
# DESCRIPTION: given the name of a parameter file with the
#              needed values (see below),
#              the environment variable SYM_TABLE to the given
#              directory and file.  This table is used by XVista
#              routines to share information between processes.
#
# USAGE:       set_sym_table   param_file
#
#                  param_file         is name of the "setup.param" file,
#                                     which contains values for
#                                            output_dir
#                                            xvista_symtable
#                                     
#
#
# RETURNS:
#     0                    if all goes well
#     1                    if an error occurs 
#
proc set_sym_table { param_file } {
  global debug env

  if { $debug > 2 } {
    puts "entering set_sym_table "
  }

  if { [file exists $param_file] != 1 } {
    puts stderr "set_sym_table: file $param_file doesn't exist"
    return 1
  }

  set dir     [get_param $param_file "output_dir"]
  set file    [get_param $param_file "xvista_symtable"]

  set fullname $dir/$file
  set cmd "array set env { SYM_TABLE $fullname }"
  if { $debug > 1 } {
    puts "set_sym_table: going to eval $cmd"
  }
  eval $cmd

  # sanity check
  set val $env(SYM_TABLE)
  if { [string compare $val $fullname] != 0 } {
    puts stderr [format "set_sym_table: set SYM_TABLE to %s, but get %s " \
                        $fullname $val ]
    return 1
  }

  return 0
}








############################################################################
# Here, we start the namespace "Directory", which we use to store
#   information about the directories in which various programs live.
#   
namespace eval Directory {
  namespace export init_directory get_directory
  variable XVista_Dir {}
  variable Match_Dir {}
  variable Photom_Dir {}
  variable Bait_Dir {}


  ##########################################################################
  # Set the variables in the "Directory" namespace, based on values
  #    in the "setup" param file.
  #
  # RETURNS:
  #     0                if all goes well
  #     1                otherwise
  #
proc init_directory { param_file } {
  global debug
  variable XVista_Dir 
  variable Match_Dir 
  variable Photom_Dir 
  variable Bait_Dir

  if { $debug > 0 } {
    puts "entering init_directory"
  }
  if { [file exists $param_file] == 0 } {
    puts stderr "init_directory: can't find param file $param_file"
    return 1
  }

  set XVista_Dir [get_param $param_file "xvista_dir"]
  set Match_Dir  [get_param $param_file "match_dir"]
  set Photom_Dir [get_param $param_file "photom_dir"]
  set Bait_Dir   [get_param $param_file "bait_dir"]
  if { $debug > 1 } {
    puts "init_directory: we have $XVista_Dir $Match_Dir $Photom_Dir $Bait_Dir"
  }


  return 0

}



  ############################################################################
  # Return the value of the given directory.
  #
  # usage:   get_directory     dir
  # 
  #                dir            is one of  "xvista_dir"
  #
  # Returns:
  #    value of the given directory      if it exists
  #    {}                                otherwise
  #
proc get_directory { dir } {
   global debug
   variable XVista_Dir 
   variable Match_Dir 
   variable Photom_Dir 
   variable Bait_Dir

   if { $debug > 1 } {
     puts "entering get_directory"
   }

   if { [string compare $dir "xvista_dir"] == 0 } {
     return $XVista_Dir
   }
   if { [string compare $dir "match_dir"] == 0 } {
     return $Match_Dir
   }
   if { [string compare $dir "photom_dir"] == 0 } {
     return $Photom_Dir
   }
   if { [string compare $dir "bait_dir"] == 0 } {
     return $Bait_Dir
   }

   return {}
}

}
# end of namespace for Directory
