#!/bin/sh

# /bin/sh interprets this part, but wish ignores it...
#\
exec wish "$0" "$@"
#geodas requires tcl 8.0 or better

#GEODAS Grid Translator
#Written by: 
#    Dan Metzger,2001





######################
### proc open_grid ###
######################
proc open_grid {} {
global headGRD
global inpPathFile 
global inpPath
global inpFile
global inpExt
global fieldsGRD
global _settings
global _databases
global _paths
global _blocksizes
global _latcellsizes
global _loncellsizes
global _ngdcprefixes
global _pathconfig 
global _headGRD 
global _options
global _grids
global _dbaselist 

    set gridMode "gmOPENGRID"
    set _dbaselist " "
    gauge_value .fr.gauge 0
    set inpPath [file dirname $inpPathFile]
    set inpFile [file tail $inpPathFile]
    set inpExt [file extension $inpFile]
    #tk_messageBox -message "$inpPathFile\n$inpPath\n$inpFile\n$inpExt"

    #now get the grid header as list of 19 numeric fields
    set hdlist [fgridget $inpPathFile] ;#reads header from file

    #tk_messageBox -message "hdlist:$hdlist"
    #foreach item $hdlist {
    #puts "item:$item"
    #}

    for {set i 0} {$i < 32} {incr i} {
      set headGRD([lindex $fieldsGRD $i]) [lindex $hdlist $i]
    }

    #for {set i 0} {$i < 32} {incr i} {
      #puts "[lindex $fieldsGRD $i] $headGRD([lindex $fieldsGRD $i])"  
    #}

    #tk_messageBox -message "dialog_gridparams headGRD $gridMode"


#we are not going to pursue this track anymore!
#   deterimine if this is a standard 1201x1201 1-deg grid (if ngdcid can be made)
 #   set ngdcid [get_ngdcid headGRD]
    #puts "got ngdcid:$ngdcid"
#   if calculated ngdcid is in _grids array, we can assume opened file is from the cd,
#   or at least it would match up with the cd grids
#   this means grid-radius, water-datum, land/sea could be applied
#   sample line of grddas.inv -> set _grids(gna44070) "grddas01.g03"
 #   set canusecd 0 ;#cannot use grid-radius, local water datums, land/sea 
 #   if {$ngdcid != ""} {
 #     foreach grid [array names _grids] {
 #       if {$ngdcid == $grid} {
 #         set canusecd 1 
 #       }
 #     }
 #   } ;#if

    .menubar.mFile entryconfigure "Open Grid File" -state disabled
    .menubar.mFile entryconfigure "Design-a-Grid" -state disabled
    #wm withdraw .

    set cando_gridradius 0
    set cando_localwater 0
    set cando_landsea 0
    set csizeminimun $headGRD(latCellSize)
    
    set result [dialog_gridparams $gridMode $cando_gridradius $cando_localwater $csizeminimun]

    #grab .

    if {$result} {
      set result [dialog_gridoptions $gridMode $cando_landsea]
    } ;#if result (dialog_gridparm)

    if {$result} { ;#i.e. if dialog_gridparams and dialog_gridoptions both successful
      #notice we dont save the headGRD values (from input file) here
      set savedconfig [save_config $_pathconfig]
      #puts "_options(dataFormat):$_options(dataFormat)"
      #puts "save_config result:$savedconfig"
      set result [translate_grid headGRD]
    }

    if {$result == 0} { ;#cancel on dialog_gridparmas, grid_options or grid_translate(Save)
      .menubar.mFile entryconfigure "Open Grid File" -state normal
      .menubar.mFile entryconfigure "Design-a-Grid" -state normal
      #wm deiconify .
    }
} ;#proc open_grid




########################
### proc design_grid ###
########################
proc design_grid {} {
global headGRD
global inpPathFile 
global inpPath
global inpFile
global inpExt
global fieldsGRD
global _settings
global _databases
global _paths
global _blocksizes
global _latcellsizes
global _loncellsizes
global _ngdcprefixes
global _pathconfig 
global _headGRD 
global _options
global _grids
global _gridbases
global _dbaselist 

  set gridMode "gmDESIGNGRID"
  gauge_value .fr.gauge 0
  set inpPath [file dirname $inpPathFile]
  set inpFile [file tail $inpPathFile]
  set inpExt [file extension $inpFile]
  array set headGRD [array get _headGRD] ;#use header from geodas.cfg
  #parray headGRD
  set headGRD(minValue) 0 ;#-99999
  set headGRD(maxValue) 0 ;#99999
  set canusecd 1 ;#true
  .menubar.mFile entryconfigure "Open Grid File" -state disabled
  .menubar.mFile entryconfigure "Design-a-Grid" -state disabled
  #wm withdraw .

  set cando_gridradius 0
  set cando_localwater 0
  set cando_landsea 0

  set result [dialog_grid_database] ;#sets those to be used in _dbaselist
 #puts "_dbaselist:$_dbaselist"
  if {$result} {
    if {[llength $_dbaselist] == 1} {
    set dbase [lindex $_dbaselist 0]
      if {$dbase == "grdcrm"} {
        set cando_gridradius 1
        set cando_landsea 1
      }
    }
    set csizeminimun 0
    foreach dbase $_dbaselist {
      if {$_latcellsizes($dbase) > $csizeminimun} {
        set csizeminimun $_latcellsizes($dbase)
      }
      if {$dbase == "grdglb"} {
        set cando_localwater 1
      }
    }

    if {$headGRD(latCellSize) < $csizeminimun} {
      set headGRD(latCellSize) $csizeminimun
      set headGRD(lonCellSize) $csizeminimun
    }
  }

  if {$result} {
    set result [dialog_gridparams $gridMode $cando_gridradius $cando_localwater $csizeminimun]
  }

  if {$result} {
    set result [dialog_gridoptions $gridMode $cando_landsea]
  }

  if {$result} { ;#i.e. if dialog_gridparams and dialog_gridoptions both successful
   #parray _options
    array set _headGRD [array get headGRD] ;#update _headGRD values with headGRD
    set result [save_config $_pathconfig]
    #puts "save_config result:$result"
    set result [translate_grid headGRD]
  }

    if {$result == 0} { ;#cancel on dialog_gridparmas, grid_options or grid_translate(Save)
      .menubar.mFile entryconfigure "Open Grid File" -state normal
      .menubar.mFile entryconfigure "Design-a-Grid" -state normal
      #wm deiconify .
    }
} ;#design_grid



###########################
### proc translate_grid ###
###########################
proc translate_grid { _headGRD } {
global tcl_platform
global _paths
global _pathconfig
global _blocksizes
global _latcellsizes
global _loncellsizes
global _ngdcprefixes
global _dbaselist
global _options
global _active
global inpPathFile 
global inpPath
global inpFile
global inpExt
global outPathFile
global outPath
global outFile
global outExt

  upvar $_headGRD headGRD

  switch $_options(dataFormat) {
    dfGRD {
      set outExt .g98
      set filetypes_out {
        { "NGDC Binary Raster Format" { .g98 }}
      }
    }
    dfARD {
      set outExt .asc
      set filetypes_out {
        { "ASCII Raster Values" { .asc }}
      }
    }
    dfXRD {
      set outExt .xyz
      set filetypes_out {
        { "Delimited lon,lat,depth" { .xyz }}
      }
    }
  } ;#switch $_options(dataFormat)

  set outPathFile [tk_getSaveFile -initialdir $outPath -defaultextension $outExt \
       -filetypes $filetypes_out -title "Save Grid File As" -parent .]
  if {$outPathFile == ""} {
    return 0
  }

  set outPath [file dirname $outPathFile]
  set outFile [file tail $outPathFile]
  set outExt [file extension $outFile]
  #tk_messageBox -message "$inpPathFile\n$inpPath\n$inpFile\n$inpExt"

  set launchstring "|$_paths(prog)/gx_gtran $tcl_platform(byteOrder) $inpPath $inpFile $outPath $outFile \
  $_paths(support)/inv $_paths(cd)  $_pathconfig $headGRD(dataType) $headGRD(latDeg) $headGRD(latMin) \
  $headGRD(latCellSize) $headGRD(latNumCells) $headGRD(lonDeg) $headGRD(lonMin) $headGRD(lonCellSize) \
  $headGRD(lonNumCells) $headGRD(gridRadius) $headGRD(precision) $headGRD(NaNvalue) $headGRD(numType) \
  $headGRD(waterDatum) $_options(dataFormat) $_options(byteOrder) $_options(headerStyle) \
  $_options(emptyCells) $_options(recordDelimiter) $_options(dataExtent) $_dbaselist"
  if [string match DEBUG [string range $outFile 0 4]] {
    puts $launchstring
  }
  set _active [open $launchstring r+]
  .fr.cancel configure -state active
  fileevent $_active readable {
  if [eof $_active] {
    set mess "An error occurred. GridTranslator program ended prematurely!^GEODAS ERROR^ERROR"
  } else {
    gets $_active mess
  }
  if [string match DEBUG [string range $outFile 0 4]] {
    if ![string match *PROGRESS* $mess] {
      puts $mess
    }
  }
  set ndx1 [string first ^ $mess]
  set ndx2 [string last ^ $mess] 
  set msg [string range $mess 0 [expr $ndx1 - 1]]
  set caption [string range $mess [expr $ndx1 + 1] [expr $ndx2 -1]]
  set mtype [string range $mess [expr $ndx2 + 1] end]
  #replace | with \n
  set ndx1 [string first | $msg]
  while {$ndx1 != -1} {
    set msg "[string range $msg 0 [expr $ndx1 - 1]]\n[string range $msg [expr $ndx1 + 1] end]"
    set ndx1 [string first | $msg]
  }
  switch $mtype {
    ERROR {
      catch {close $_active}
      .fr.cancel configure -state disabled
      tk_messageBox -icon error -title $caption -message "$msg"
      .menubar.mFile entryconfigure "Open Grid File" -state normal
      .menubar.mFile entryconfigure "Design-a-Grid" -state normal
      #wm deiconify .
    }
    STATUS {
    .status configure -text $msg
    update
    }
    OK {
      tk_messageBox -type ok -icon info -title $caption -message "$msg"
      puts $_active "OK"
      flush $_active
    }
    OKCANCEL {
      set result [tk_messageBox -type okcancel -icon info -title $caption -message "$msg"]
      if [string match ok $result] { 
        puts $_active OK
        flush $_active
      } else {      
        puts $_active CANCEL
        flush $_active
        catch {close $_active}
        .fr.cancel configure -state disabled
        .menubar.mFile entryconfigure "Open Grid File" -state normal
        .menubar.mFile entryconfigure "Design-a-Grid" -state normal
        #wm deiconify .
      }
    }
    OKCANCELIGNORE {
      set result [tk_dialog .dialog $caption $msg info 0 Ok Cancel Ignore]
      if {$result == 0} {
        puts $_active OK
        flush $_active
      } elseif {$result == 1} {
        puts $_active CANCEL
        flush $_active
        catch {close $_active}
        .fr.cancel configure -state disabled
        .menubar.mFile entryconfigure "Open Grid File" -state normal
        .menubar.mFile entryconfigure "Design-a-Grid" -state normal
        #wm deiconify .
      } elseif {$result == 2} {
        puts $_active IGNORE
        flush $_active
      }
    }
    PROGRESS {
      gauge_value .fr.gauge $msg
      update
    }
    INPUT {  ;#we are assuming the response is a path
      set ndx1 [string first \[ $msg]
      set ndx2 [string first \] $msg]
      set response [string range $msg [expr $ndx1 + 1] [expr $ndx2 - 1]] ;#default response
      set oldpath [string trimright $response /]
      set msg [string range $msg 0 [expr $ndx1 - 1]]
      set result [my_inputdialog $caption $msg response]
      if {$result} {  ;#if OK pressed
        #expand ~/ if found
        set ndxp [string first / $response]
        if [string match ~ [string range $response 0 0]] {
          if {$ndxp == 1} {
            set response "[glob ~][string range $response 1 end]"
          } else {
            set str [string range $response 0 [expr $ndxp - 1]]
            set response "[glob $str][string range $response $ndxp end]"
          }
        }
        set response [string trimright $response /]
        if ![string match $response $oldpath] {
          set ndxv [string first Volume $msg]
          set _paths(VOL_GRDDAS[string range $msg [expr $ndxv + 7] [expr $ndxv + 8]]) $response
          set result [save_config $_pathconfig]
        }
        puts $_active $response
        flush $_active
      } else {        ;#if Cancel pressed
        puts $_active "CANCEL"
        flush $_active
        catch {close $_active}
        .fr.cancel configure -state disabled
        .menubar.mFile entryconfigure "Open Grid File" -state normal
        .menubar.mFile entryconfigure "Design-a-Grid" -state normal
        #wm deiconify .
      }
    }
    END {
      # an error occurs during the download process - when Tcl closes
      # a process pipeline, it outputs any outstanding errors.  Pg
      # 106, Welch.  We're not sure what this error is.  Downloads 
      # seem to be fine, regardless. jbh, 7/98
      catch {close $_active} IEE_error
      .fr.cancel configure -state disabled
      tk_messageBox -type ok -icon info -title $caption -message "$msg"
      .menubar.mFile entryconfigure "Open Grid File" -state normal
      .menubar.mFile entryconfigure "Design-a-Grid" -state normal
      #wm deiconify .
    }
    default {
      #puts $mess
    }
  } ;#switch

  } ;#fileevent
  return 1
} ;#proc translate_grid



#######################
### proc get_ngdcid ###
#######################
proc get_ngdcid { _headGRD } {
  upvar $_headGRD headGRD

  set ngdcid ""

  set latsecdif [expr $headGRD(latCellSize) * ($headGRD(latNumCells)-1)]
  set lonsecdif [expr $headGRD(lonCellSize) * ($headGRD(lonNumCells)-1)]

# if exactly a one degree grid, bounded at whole degree
  if {$headGRD(latMin) == 0 && $headGRD(lonMin) == 0 && $latsecdif == 3600 && $lonsecdif == 3600} {
    if {$headGRD(latDeg) >= 0} {
      if {$headGRD(lonDeg) >= 0} {
        set ngdcid gnb
      } else {
        set ngdcid gna
      }
    } else {
      if {$headGRD(lonDeg) >= 0} {
        set ngdcid gnc
      } else {
        set ngdcid gnd
      }
    }
    set abslatdeg [expr abs($headGRD(latDeg))]
    set abslondeg [expr abs($headGRD(lonDeg))]
    set ngdcid [format "%s%02d%03d" $ngdcid $abslatdeg $abslondeg]
  }

  return $ngdcid

} ;#get_ngdcid


########################
### main starts here ###
########################

#element names for headGRD arrays
lappend fieldsGRD version   ;#1,000,000,001 (version 1)
lappend fieldsGRD length    ;#128 bytes (32 fields)
lappend fieldsGRD dataType  ;#1=data  2=data-density  3=grid-radius  -1=template
lappend fieldsGRD latDeg     ;#upper
lappend fieldsGRD latMin
lappend fieldsGRD latSec
lappend fieldsGRD latCellSize
lappend fieldsGRD latNumCells
lappend fieldsGRD lonDeg      ;#left
lappend fieldsGRD lonMin
lappend fieldsGRD lonSec
lappend fieldsGRD lonCellSize
lappend fieldsGRD lonNumCells
lappend fieldsGRD minValue        ;#per precsion
lappend fieldsGRD maxValue
lappend fieldsGRD gridRadius     ;#0 to 110, -1=not applied
lappend fieldsGRD precision      ;# 1= whole meters, 10 = tenths of meters
lappend fieldsGRD NaNvalue       ;#999999(4-byte) -32768(2-byte)
lappend fieldsGRD numType  ;#bytesize, pos=integer, neg=float (e.g. +4=4-byte-int)
lappend fieldsGRD waterDatum  ;#vertical datum 0=Mean Sea Level 1=Local Datum
lappend fieldsGRD dataLimit ;#maximum calculated cell value 0=not applicable
lappend fieldsGRD unused1
lappend fieldsGRD unused2
lappend fieldsGRD unused3
lappend fieldsGRD unused4
lappend fieldsGRD unused5
lappend fieldsGRD unused6
lappend fieldsGRD unused7
lappend fieldsGRD unused8
lappend fieldsGRD unused9
lappend fieldsGRD unused10
lappend fieldsGRD unused11

lappend optionsGRD dataFormat   ;# dfNONE, dfGRD, dfARD, dfXRD
lappend optionsGRD byteOrder   ;# boNONE, boLITTLEENDIAN, boBIGENDIAN
lappend optionsGRD headerStyle   ;# hsNONE, hsGRDNGDC, hsGRDARCINFO
lappend optionsGRD emptyCells   ;# ecNONE, ecINCLUDE, ecEXCLUDE
lappend optionsGRD recordDelimiter  ;# rdNONE, rdSPACE, rdTAB, rdCOMMA
lappend optionsGRD dataExtent  ;# deNONE, deALL, deLAND, deSEA

#tk_setPalette lightgrey
#tk_setPalette #9FB7C0
#tk_setPalette palegreencd
#tk_setPalette lightsteelblue

  #tk_messageBox -message "argc:$argc| argv:$argv|"


set filetypes_grd {
  { "GEODAS GRD98 Grids" { .g98 .g03 }}
}


option add *Entry.relief sunken startupFile
option add *Entry.borderWidth 3 startupFile

set _paths(home) ""

#set directory variables
set _pathconfig ""
if [file readable ./geodas.cfg] {
  set _pathconfig "."
} elseif [file readable $env(HOME)/geodas/geodas.cfg] {
  set _pathconfig $env(HOME)/geodas
} elseif [file readable $env(HOME)/gdas/geodas.cfg] {
  set _pathconfig $env(HOME)/gdas
} else {
  set temp $env(PATH)
  regsub  -all ":" $temp " " temp ;#make path into list
  foreach i $temp {
    if [file readable $i/geodas.cfg] {
      set _pathconfig $i
      break
    }
  }
}

 #puts "_pathconfig:$_pathconfig"
#sourceing geodas.cfg gives us:
#  _settings
#  _databases
#  _paths
#  _blocksizes
#  _latcellsizes
#  _loncellsizes
#  _ngdcprefixes
#  _headGRD
#  _options

if [file readable $_pathconfig/geodas.cfg] {
  source $_pathconfig/geodas.cfg
} else {
   tk_messageBox -message "Could not find a geodas.cfg in current or in PATH"
   exit
}

load $_paths(lib)/libgeodastcl.so Geodastcl   ;#load the geodas commands

catch {
  tk_setPalette $_settings(colorscheme)
}

foreach dbase [lsort [array names _databases]] {
  if [string match grd??? $dbase] {
    set _gridbases($dbase) "$_databases($dbase)"
  }
}
 #parray _gridbases

####
#### GEODAS Help System based on html_library (see file html_library for licence terms)
####
source $_paths(lib)/html_library
global help_initialized
global _contents
global _index
set help_initialized 0
set _contents cont_gt.htm
set _index index_gt.htm

# tk_messageBox -message "grddas.inv:$_paths(grddas)/grddas.inv"
#sourcing grddas.inv gives us: _grids
#if [file readable $_paths(grddas)/grddas.inv] {
#  source $_paths(grddas)/grddas.inv
#} else {
#   tk_messageBox -icon error \
#         -message "Could not find Coastal Relief Model Inventory\n Re-Install GEODAS Coastal Relief Model"
#   exit
#}


#check here for prog path, check where needed for other paths...
if {![info exists _paths(prog)] || $_paths(prog)==""} {
   tk_messageBox -message "geodas.cfg error -- no program path found!"
   exit
}

#expand ~/ if found in work path
if [string match ~ [string range $_paths(work) 0 0]] {
  set _paths(work) "[glob ~][string range $_paths(work) 1 end]"
}
set inpPath $_paths(work)
 #puts "inpPath:$inpPath"
set outPath $_paths(work)


set auto_path "$_paths(prog) $auto_path" ;#extend auto_path to include programs (tcl)

if {![info exists _paths(work)] || $_paths(work)==""} {
   tk_messageBox -message "Geodas.ini error -- work path not available/specified!\nRun gdsettings"
   exit
}
 #tk_messageBox -message "this is path to work: $_paths(work)"
if {![file isdirectory $_paths(work)]} {
   file mkdir $_paths(work)
}



#initialize the main window
wm title . "GEODAS Grid Translator" 
wm geometry . "+100+175"
wm iconbitmap . "@$_paths(images)/geodas.ico"
wm protocol . WM_DELETE_WINDOW {
  exit
}

menu .menubar
#attach to main window
. config -menu .menubar
set File [menu .menubar.mFile -tearoff 0]
.menubar add cascade -label File -underline 0 -menu .menubar.mFile
set Help [menu .menubar.mHelp -tearoff 0]
.menubar add cascade -label Help -underline 0 -menu .menubar.mHelp

$File add command -label "Open Grid File" -underline 0 -command {
  set inpPathFile [tk_getOpenFile -initialdir $inpPath -filetypes $filetypes_grd \
                -title "Open NGDC Grid File" -parent .]
  if {$inpPathFile != ""} {
    open_grid 
  } ;#if {$inpPathFile != ""}
} 

$File add command -label Design-a-Grid -underline 0 -command {
  set inpPathFile $_paths(cd)/grddasxx/griddata/template.g03
  design_grid
} 

$File add separator

$File add command -label Exit -underline 1 -command exit

$Help add command -label "Help Contents" -underline 0 -command {
  help $_contents
}

$Help add command -label "About GEODAS" -underline 0 -command {
  about "GEODAS Grid Translator" geodas.gif
}

frame .fr

gauge_create .fr.gauge 300 PaleGreen
#pack .gauge -expand yes -fill both -padx 10 -pady 10

button .fr.cancel -text "Cancel" -underline 0 -state disabled -command {
  catch {close $_active}
  .fr.cancel configure -state disabled
  tk_messageBox -message "Grid Canceled!" -icon warning
  .menubar.mFile entryconfigure "Open Grid File" -state normal
  .menubar.mFile entryconfigure "Design-a-Grid" -state normal
  #wm deiconify .
}
pack .fr.gauge .fr.cancel -side left
set help_tips(.fr.cancel) "Click to stop Grid!"

label .status -relief sunken -anchor w -borderwidth 1 
 
pack .fr -side top
pack .status -fill x -side bottom

tkwait visibility .

#set result [tk_messageBox -icon warning -message "THIS DATA IS NOT TO BE USED FOR NAVIGATION\n\n\
#Although these data are of high quality and useful for planning and modeling purposes,\
#as an historical data set these data do not necessarily reflect current conditions, nor\
#do they depict data which is on a nautical chart.\n\n\
#For navigation please refer to the NOS nautical chart series." -type okcancel]
#if [string match cancel $result] {
#  exit
#}

 #puts "argc:$argc"
#this (below) doesnt seem to do anything (argc is 0)
if {$argc > 0} {
#  set inpPathFile [lindex $argv 0]
#  puts "inpPathFile:$inpPathFile"
#  if [string match template.??? $inpPathFile] {
#    design_grid
#  } else {
#    open_grid
#  }
#}

#end of main program




