#!/usr/bin/env tclsh9.0 
lappend auto_path  $::env(LUSTRE_INSTALL)/tcl9
package require Luciole 2.0
# luc package is used only to display std options
##########################################################
# luciole v2 main script 
##########################################################

# parse args
set Param(tool) [file tail $argv0]
set Param(verbose) 0
set Param(guiopts) {}
set Param(others) {}
# lustre = lv6, lv4 
set Param(lv6) 0
# compil = ec, dro 
set Param(dro) 0
set Param(pipe) 0

proc version { } {
	puts -nonewline "2.04.c"
}

# 2.04.c
# better file arg filter
#
# 2.04.b
# 25/09/30  rifexe feature, several fixes to gat sim2chro working

# 2.04.a
# 25/09/18 "-pipe cmd" should exit (and no longer freeze) if something goes wrong in cmd
#
# 2.04
# 25/05/16 - pipe support 
#
# 2.03
# 25/05/16 - bug in 'Save luc' (luciolerc.tcl)

proc usage { ch } {
   global Param
   puts $ch "Usage: $Param(tool) <prg spec> \{ <opts> \} \[-- \{ <gui option> \}\]"
   puts $ch "prg-spec:"
   puts $ch "  <file.luc>"
   puts $ch "  <file.dro>"
   puts $ch "  <file.ec>"
   puts $ch "  <file.lus> \{ <file.lus> \} <node> \[ <compiler> \]"
   puts $ch "  -pipe <command>"
   puts $ch "opts:"
   puts $ch "  -lv6"
   puts $ch "  -dro"
   puts $ch "gui option:"
	luc::print_options $ch
}

proc parse_args { } {
	global Param
	set sepix [lsearch $::argv "--"]
#puts "sepix=$sepix"
	if { $sepix >= 0 } {
		set myargs [lrange $::argv 0 $sepix-1] 
		set Param(guiopts) [lrange $::argv $sepix+1 end] 
	} else {
		set myargs $::argv 
		set Param(guiopts) {}
	}
#puts DBG:myargs=$myargs
#puts DBG:Param(guiopts)=$Param(guiopts)
	foreach a $myargs {
#		switch -glob -matchvar flgs $a 
		switch -glob $a {
			-h { usage stdout ; exit 0 }
			-version { version ; exit 0 }
			--version { version ; exit 0 }
			-v { set Param(verbose) 1 }
			-lv6 { set Param(lv6) 1 }
			-dro { set Param(dro) 1 }
			-pipe { set Param(pipe) 1 }
			-* { puts stderr "unknown flag '$a'" ; usage stderr; exit 1 } 
			default { lappend Param(others) $a }
		}
	}
#puts DBG:Param(others)=$Param(others)
}

#
# ERROR handling
#
# Try to adopt a 'clean' raise/trap 
#

proc _failure { msg } {
	throw LUC_FAILURE $msg
}

proc verbose { msg } {
   global Param
   if { $Param(verbose) } {
      puts stderr "#$Param(tool): $msg"
   }
}


proc main { argc argv } {
	try {
		# NO MAIN WINDOW
		wm withdraw .
		global Param
		parse_args
		set nb_others [llength $Param(others)]
		if { $Param(pipe) } {
			dopipe [lindex $Param(others) 0]
		} else { 
			switch -glob $nb_others {
				0 { helper }
				1 { dofile [lindex $Param(others) 0] }
				* {
					dofilesnode [lrange $Param(others) 0 end-1] [lindex $Param(others) end]
				}
			}
		}
	} trap LUC_FAILURE msg {
		puts stderr "luciole failure: $msg"
		exit 1
	}  on error { res other } {
		set ec [dict get $other "-errorcode"]
		puts stderr "luciole: uncaught exception '$ec'"	
		puts stderr "   details: $res"
		exit 1
	}
}

# Treat single file (luc, ec or dro)
proc dofile { zefile } {
	set ext [file extension $zefile]
	verbose "load file '$zefile', ext '$ext'"
	switch -glob $ext {
		".luc" { doluc $zefile }
		".ec"  { dorp  $zefile ecexe }
		".dro" { dorp $zefile droexe }
		".lus" { _failure "node parameter required for lustre files" }
		".lv6" { _failure "node parameter required for lustre files" }
		* { _failure "unknown extension '$ext'" }
	}
}

proc catch_exec { args } {
	if { [ catch { exec {*}$args } res ] } {
		_failure $res
	}
}

# Exec a luc file
proc doluc { zefile } {
	global Param
	if [file exists $zefile] then {
		# not sure x flag is set ...
		catch_exec tclsh9.0 "$zefile" {*}$Param(guiopts) <@stdin >@stdout 2>@stderr
	} else {
		_failure "file '$zefile' does not exist"
	}
}

# 2025
# - does not use rp2luc to launch the gui
# - generates the luc file
# - exec the luc file

proc dorp { zefile kind } {
	global Param
	# create a temp file HERE ".basename.luc"
	set basename [file rootname [file tail $zefile]]
	set lucfile ".$basename.luc"
	verbose "# create '$lucfile'"
	# what to do with {*}$Param(guiopts) ?
	# external code called within rp2luc may write to stderr
	verbose "# rp2luc $kind $zefile $lucfile"
	catch_exec rp2luc $kind $zefile $lucfile 2>@stdout
	file attributes $lucfile -permissions +x
	verbose "# runs '$lucfile'"
	catch_exec "./$lucfile" $Param(guiopts) <@stdin >@stdout 2>@stderr
}

proc dopipe { cmd } {
	global Param
	set lucfile "._unnamed_.luc"
	verbose "# create '$lucfile'"
	catch_exec rp2luc pipexe $cmd $lucfile 2>@stdout
	file attributes $lucfile -permissions +x
	verbose "# runs '$lucfile'"
	catch_exec "./$lucfile" $Param(guiopts) <@stdin >@stdout 2>@stderr
}


proc dorp_0 { zefile ext } {
	global Param
# NO A GOOD IDEA !
#	set lucfile [] if [ luc_exists $zefile $ext lucfile ] {
#		verbose "doluc '$lucfile'"
#		doluc $lucfile
#	} else {
		catch_exec rp2luc $zefile {*}$Param(guiopts) <@stdin >@stdout 2>@stderr
#	}
}
proc luc_exists { zefile ext res } {
	upvar $res lucfile
	global Param
	if { ! [file exists $zefile] } then {
		_failure "file '$zefile' does not exist"
	}
	set root [file rootname $zefile]
	set lucfile $root.luc
	if [file exists $lucfile] then {
		#TODO check if compatible with $zefile
		return yes
	}
	return no
}



proc warn_yesno { msg dflt } {
	set res [tk_messageBox -title "Luciole Warning" -type yesno -default $dflt \
		-detail $msg  -icon warning]
	#tcl bug ? message box freezed, force update
	update idletasks
	return $res
}

# Treat file + node (lus/lv6 or dro)
proc dofilesnode { zefiles zenode } {
	global Param
#puts "BG dofilesnode"
	foreach zefile $zefiles {
		if { ! [file exists $zefile] } then {
			_failure "file '$zefile' does not exist"
		}
	}
	if { [file exists $zenode.ec] && \
        ! [warn_yesno "erase existing '$zenode.ec' ?" yes] } { exit 0 }
	set ecfile $zenode.ec
	#lassign [chan pipe] pinc poutc
	exec rm -f $ecfile
	# lus2ec or lv6 ?
   if { $Param(lv6) } {
		set ko [catch {exec lv6 -ec {*}$zefiles -n $zenode -o $ecfile} err]
		if $ko {
			_failure "lv6 failed:\n $err"
		}
	} else {
		if { [llength $zefiles] != 1 } {
			_failure "lus2ec expect a single input files"
		}
		set ko [catch {exec lus2ec {*}$zefiles $zenode -o $ecfile} err]
		if $ko {
			_failure "lus2ec failed:\n $err"
		}
	}
	# exec ec or dro ?
	if { $Param(dro) } {
		set drofile $zenode.dro
		if { [file exists $drofile] && \
        	! [warn_yesno "erase existing '$drofile' ?" yes] } { exit 0 }
		set ko [catch {exec ec2dro $ecfile} err]
		if $ko {
			_failure "ec2dro failed:\n $err"
		}
		dorp $drofile ".dro"
	} else {
		dorp $ecfile ".ec"
	}
}

# Luciole helper
source "$env(LUSTRE_INSTALL)/tcl/utiles.tcl"
source "$env(LUSTRE_INSTALL)/tcl/select-lus.tcl"
proc SelectLucioleArg { titre } {
   global SelectLusVars
   global SelectLusStrings
   set rep ""
   set ftypes [list "$SelectLusStrings(lustre_files)" {*.lus *.ec}]
   set rep [tk_getOpenFile \
      -title "$titre" \
      -defaultextension ".lus" \
      -defaultextension ".luc" \
      -defaultextension ".ec" \
      -defaultextension ".dro" \
      -filetypes { { "All recognized files"  {*.lus *.ec *.dro *.luc} } } \
   ]
   return $rep
}
proc helper { } {
	verbose "Luciole Helper"
	global COMMANDS
	global PROJECT
	set COMMANDS(lusinfo) "lusinfo"
	set PROJECT(main_type) "lus"
	set PROJECT(main_file) ""
	set PROJECT(main_node) ""
	set version "2.0"
	
	set PROJECT(main_file) [ SelectLucioleArg "Luciole launcher $version" ]
	set ext [file extension $PROJECT(main_file)]
	verbose "main_file=$PROJECT(main_file)"


	if { $ext == ".ec"  || $ext == ".dro" || $ext == ".luc" } {
		dofile $PROJECT(main_file)
	} elseif { $ext == ".lus" } {
   	global SelectLusVars
   	set SelectLusVars(type) "lus"
   	set SelectLusVars(node) ""
   	set SelectLusVars(file) "$PROJECT(main_file)"
   	SelectLusBrowseNode "Luciole launcher $version" \
      	{PROJECT} {main_file} {main_node} {main_type}
   	verbose "$PROJECT(main_file) $PROJECT(main_node)"
		dofilesnode $PROJECT(main_file) $PROJECT(main_node)
	} else {
   	exit 1
	}
}

main $argc $argv

exit 0
