# -----------------------------------------------------------------------
# luciolerc.tcl  for luciole V2 (ptk-based)
# -----------------------------------------------------------------------
# Example of resource file for luciole
# You can copy this file and customize it.
#
# Luciole will load the first existing file in the following list:
#    $PWD/luciolerc.tcl
#    $PWD/.luciolerc.tcl
#    $HOME/luciolerc.tcl
#    $HOME/.luciolerc.tcl
#    $LUSTRE_INSTALL/lib/luciolerc.tcl
#
# WARNING: This file is a tcl-tk script and it will be loaded 
# without any verification! It is strongly recommended to use
# only the variables and procedures listed here, and to respect
# the access recommendations (in particular for read-only variables).
# 
# -----------------------------------------------------------------------
# Variables (read only)    Type      Description
# -----------------------------------------------------------------------
# luc::GUI(menu_hbar)     ptk-id      Where to add extra menu stuff
#                                      (use with ptk::reopen/ptk::reclose)
# luc::GUI(files_menu)    ptk-id      Where to add extra menu stuff
#                                      (use with ptk::reopen/ptk::reclose)
# luc::GUI(clocks_menu)   ptk-id      Where to add extra menu stuff
#                                      (use with ptk::reopen/ptk::reclose)
# luc::Prg(module_name)   string      
# luc::Prg(creator)       string      
# luc::Prg(creator_arg)   string      
# luc::Prg(command)       string      
# luc::Prg(input_types)   type list
# luc::Prg(input_names)   str. list
# luc::Prg(output_types)  type list
# luc::Prg(output_names)  str. list
# luc::InputVars          data array  indexed by input_names
# luc::OutputVars         data array  indexed by output_name
# -----------------------------------------------------------------------
# Procedures           Params        Effect
# -----------------------------------------------------------------------
# luc::DBG             string         
# luc::TreatStep       none          Performs a step according to the 
#                                    current values in InputVars 
# luc::verbose_to      fileid        start to verbose on fileid
# luc::verbose_close   fileid        stop to verbose on fileid
# ----------------------------------------------------------------------
# Extra Tcl commands, from lustubs.so
# -----------------------------------------------------------------------
# add_timer <milliseconds> <script>  causes <script> to be executed 
#                                    <milliseconds> after (or more !)
#                                    returns a <timer-token> that can
#                                    used in the abort_timer command
#
# abort_timer  <timer-token>         causes the corresponding timed script
#                                    to be deleted (if it exists)
# -----------------------------------------------------------------------
#
# This example adds a new menu "Tools" in the luciole window, with :
# - a command that launches sim2chro
# - a command that read inputs from a (rif-compliant) file
# -----------------------------------------------------------------------

namespace eval LRC {
	variable tool_menu
}

# Menu 'Tools'
ptk::reopen $luc::GUI(menu_hbar)
	ptk::begin menubutton -text "Tools"
	ptk::store LRC::tool_menu
		# user tools will be inserted here
	ptk::end menubutton
ptk::reclose $luc::GUI(menu_hbar)


#-----------SIM2CHRO LAUNCHER--------------------------------------------
# New global variables :
# (pipe and pid associated to the the sim2chro process)
set LRC::S2C(thepipe) ""
set LRC::S2C(thepid) ""

# New procedures :
# (starts a new sim2chro process, kills the previous one if it exists)
# only ONE sim2cho process at the time

proc LRC::StartS2C { s2cprg } {
	#prevent violent kill on some systems
	if { $LRC::S2C(thepid) != "" } {
		catch [exec kill $LRC::S2C(thepid)]
	}
        
	set command "$s2cprg -ecran /dev/null"
	catch "LRC::KillS2C"
	set LRC::S2C(thepipe) [open |$command w+ ]
	set LRC::S2C(thepid)  [pid $LRC::S2C(thepipe)] 
	fconfigure $LRC::S2C(thepipe) -blocking 0 -buffering line

	luc::verbose_to $LRC::S2C(thepipe)
}

proc LRC::KillS2C { } {
	luc::verbose_close $LRC::S2C(thepipe)
	#prevent violent kill on some systems
	if { $S2C(thepid) != "" } {
		catch [exec kill $S2C(thepid)]
	}
}

#----------------------------------------------------------------------
# Adds StartSim2chro command to the tools menu :
# ONLY if the commands are available in the environment
#----------------------------------------------------------------------
#puts "LRC::tool_menu='$LRC::tool_menu'"
if [ catch {exec sim2chro -version} ] {
	luc::DBG "luciolerc: sim2chro NOT available"
} else {
	luc::DBG "luciolerc: sim2chro available"
	ptk::reopen $LRC::tool_menu
		ptk::add menu_command \
			-command "LRC::StartS2C sim2chro" \
			-label "sim2chro (x11)" \
   		-underline {10}
	ptk::reclose $LRC::tool_menu
}
if [ catch {exec sim2chrogtk -version} ] { 
	luc::DBG "luciolerc: sim2chrogtk NOT available"
} else {
	luc::DBG "luciolerc: sim2chrogtk available"
	ptk::reopen $LRC::tool_menu
		ptk::add menu_command \
			-command "LRC::StartS2C sim2chrogtk" \
			-label "sim2chro (gtk)" \
   		-underline {10}
	ptk::reclose $LRC::tool_menu
}

#-----------LOAD INPUT FILE--------------------------------------------
# The tool rif2tcl must be available 
proc LRC::LoadRif { } {
   #Ask for an input file
   set rep [tk_getOpenFile -title "Select input file" \
      -defaultextension ".rif" \
      -filetypes {\
         {{Reactive Input Format} {*.rif}}\
         {{All file} {*.*}}\
      }
   ]
   if {$rep == ""} {
      return
   }
   #open the pipe
   set command "rif2tcl $rep"
   set instream [open |$command r ]
   set nb_inputs [llength $luc::Global(input_names)]
   set current_input 0
   while { ! [eof $instream] } {
      if { $current_input >= $nb_inputs } {
         #copy values to input vars
         #and make a step
         array set luc::InputVars [array get cur_values]
#puts "run step proc"
#puts "current inputs are :"
#puts [array get InputVars]
#puts "perform a step ?"
#gets stdin
         luc::TreatStep
         set current_input 0
      }
      set line [gets $instream]
#puts "read line : $line"
      eval $line
      switch $RifToken {
         EOF { return }
         VALUE {
            set cur_type [lindex $luc::Global(input_types) $current_input]
            set cur_name [lindex $luc::Global(input_names) $current_input]
#puts "expected type is : $cur_type"
            if { [info exists RifValue($cur_type)] } {
               set cur_values($cur_name) $RifValue($cur_type)
            } else {
               ERROR { tk_messageBox -icon error \
                      -message "unexpected input value" -type ok }
               return
            }
            incr current_input
         }
         ERROR { tk_messageBox -icon error -message $RifError -type ok }
      }
   }
}

# TODO add a record/replay feature
# Adds LoadRif command to the tool menu :
#
# if [ catch {exec rif2tcl -version} ] { 
#	luc::DBG "luciolerc: rif2tcl NOT available"
#} else {
#	luc::DBG "luciolerc: rif2tcl available"
#	ptk::reopen $LRC::tool_menu
#		ptk::add menu_command \
#   		-command LRC::LoadRif \
#   		-label "Load RIF file" \
#   		-underline {0}
#	ptk::reclose $LRC::tool_menu
#}

#-----------SAVE BASIC LUC -------------------------------------------


proc SaveBasicLuc { } {
	# Needed vars:
	# luc::Prg(module_name)   string      
	#   the rp program name (typically the lustre node)
	# luc::Prg(file_name)     string      
	#   the rp progam file
luc::DBG "luc::Prg(module_name)=$luc::Prg(module_name)"
	set lucfile [tk_getSaveFile \
		-title {machin} \
		-initialfile "$luc::Prg(module_name)" \
		-filetypes {{"Luciole script" .luc}} \
		-defaultextension .luc \
		-confirmoverwrite yes]
luc::DBG "lucfile=$lucfile"

	if { $lucfile != "" } {
luc::DBG "exec rp2luc $luc::Prg(creator) $luc::Prg(creator_arg) $lucfile"
		# redirect stderr since it may be used for debug/verbose
		if [ catch { exec rp2luc $luc::Prg(creator) $luc::Prg(creator_arg) $lucfile 2>@1  } errmsg ] {
			tk_messageBox -icon error -type ok \
            -message "Save luc failed $errmsg"
			#exec rm -rf $lucfile
			# ICI erreur
		} else {
luc::DBG "Save luc ok"
      }
	}
}

ptk::reopen $luc::GUI(files_menu)
	ptk::add command \
   	-label {Save basic .luc script}\
   	-command SaveBasicLuc
ptk::reclose $luc::GUI(files_menu)

#-----------REAL TIME STEPS --------------------------------------------
set RTClock(period) 1000
set RTClock(buffperiod) $RTClock(period)
set RTClock(on) NO
set RTClock(token) ""
proc RealTimeStep { } {
   global RTClock
   #call a step
   if { $RTClock(on) } {
      luc::TreatStep
      set RTClock(token) [add_timer $RTClock(period) RealTimeStep]
   }
}
proc RealTimeChPeriodOut { } {
   global RTClock

   if { [string is integer $RTClock(buffperiod)]
         && ($RTClock(buffperiod) >= 0)
   } {
      set RTClock(period) $RTClock(buffperiod); \
      catch [destroy .chperiod]; \
   } else {
      tk_messageBox -icon error -type ok \
      -message "Period must be a positive integer"
   }
}

proc RealTimeChPeriod { } {
   global RTClock
   toplevel .chperiod
   wm title .chperiod "Select a period"
   wm resizable .chperiod 0 0
   frame .chperiod.top
   entry .chperiod.top.en -textvariable RTClock(buffperiod) -justify right
   bind .chperiod.top.en <Return> RealTimeChPeriodOut
   label .chperiod.top.txt -text "ms" -relief flat
   frame .chperiod.buttons
   button .chperiod.buttons.ok -text "Ok" \
      -command RealTimeChPeriodOut
   button .chperiod.buttons.cancel -text Cancel \
      -command { catch [destroy .chperiod]; return }

   pack .chperiod.top -side top -fill x
   pack .chperiod.top.en -side left -fill x
   pack .chperiod.top.txt -side left -fill x
   pack .chperiod.buttons -side bottom -fill x
   pack .chperiod.buttons.ok -side left -anchor center -expand yes -fill x
   pack .chperiod.buttons.cancel -side left  -anchor center  -expand yes -fill x

   tkwait window .chperiod
}

# Menu 'CLocks'
ptk::reopen $luc::GUI(clocks_menu)
	ptk::add checkbutton \
   	-variable RTClock(on) \
   	-onvalue "YES" \
   	-offvalue "NO" \
   	-label {Real time clock} \
   	-command RealTimeStep \
   	-underline {0}
	ptk::add command \
   	-label {Change Period}\
   	-command RealTimeChPeriod
ptk::reclose $luc::GUI(clocks_menu)

# smart input -> to do

