
# Stuff for opening jobs.
#
# Copyright (c) 2001 ICEM CFD Engineering
# Author:  Wayne A. Christopher, wayne@icemcfd.com
#

proc file_new {} {
    global job_name default_job_directory app_name
    
    if [db_check_dirty model] {
	set message "Current project has been modified --\
                             save before switching projects?"
	switch [tk_dialog .confirm Confirm $message "" 0 "Save" \
		    "Don't save" "Cancel switch"] {
			0 { file_save 1 "" }
			2 { return 0 }
		    }
    }
    
    if {[info command app_create_new_project] != ""} {
	return [app_create_new_project]
    }
    
    if {$job_name == ""} {
	if {$default_job_directory == ""} {
	    set dir [pwd]
	} else {
	    set dir $default_job_directory
	}
    } else {
	set dir [file dirname $job_name]
    }
    
    set nn [file_selection -message "Select a new project." \
		-dir_leaf_image ${app_name}_is_job -dir_leaf_label "Project" \
		-default $dir/ -title "New project" \
		-ok_func directory_is_job_new \
		-get_dir 1 -new_ok 1 -warn_overwrite 1 \
		-open_button_name Create]
    if {$nn == ""} { return 0 }
    
    if [file exists $nn] { cmd_rm_r $nn }
    
    if ![job_load $nn ""] { return 0 }
    
    # Just save the empty job now so that if we exit and reopen it,
    # it looks like a job.
    job_save $nn ""
    return 1
}

proc new_project_entry {w var tabgeo {act ""}} {
    set r [lindex $tabgeo 0]; set c [lindex $tabgeo 1]
    set cols 1; set anch w; set rows 1
    for {set i 2} {$i < [llength $tabgeo]} {incr i} {
	case [lindex $tabgeo $i] in {
	    -cols   { set cols [lindex $tabgeo [expr {$i + 1}]] }
	    -rows   { set rows [lindex $tabgeo [expr {$i + 1}]] }
	    -anchor { set anch [lindex $tabgeo [expr {$i + 1}]] }
	}
    }
    form_entry $w $var string $tabgeo $act
    $w configure -justify right
    $w xview end
    incr c $cols
    form_button ${w}_menu "Browse" "new_project_file_select $var" \
	"$r $c -rows $rows -anchor $anch -fill none" $act
}

proc new_project_file_select {var} {
    global app_name env
    
    upvar \#0 $var lvar
    if {$lvar == ""} {
	if [info exists env(ICEPAK_JOB_DIRECTORY)] {
	    set lvar $env(ICEPAK_JOB_DIRECTORY)/
	} else {
	    set lvar [pwd]/
	}
    }
    
    set nn [file_selection -message "Select a new project." \
		-dir_leaf_image ${app_name}_is_job -dir_leaf_label "Project" \
		-default $lvar -title "New project" \
		-ok_func directory_is_job_new \
		-get_dir 1 -new_ok 1 -warn_overwrite 0 \
		-open_button_name Create]
    if {$nn != ""} { set lvar $nn }
}

proc file_job {} {
    global job_open icepak_root job_name default_job_directory
    global can_do_open_operation tcl_version app_name
    global file_job_server_info env app_name
    
    if [db_check_dirty model] {
	set message "Current project has been modified --\
                             save before switching projects?"
	switch [tk_dialog .confirm Confirm $message "" 0 "Save" \
		    "Don't save" "Cancel switch"] {
			0 { file_save 1 "" }
			2 { return 0 }
		    }
    }
    
    if ![info exists job_open(location)] {
	if {[info exists env(HOME)] && \
		[file exists $env(HOME)/.${app_name}_file_open]} {
	    if [catch {source $env(HOME)/.${app_name}_file_open} res] {
		user_error $res
	    }
	}
	if {[info exists job_open(location)] && 
	    ($job_open(location) != "local")} {
	    file_job_select_server
	}
    }
    
    # sometimes users are too quick giving this command and get into a
    # recursive file/open situation  But maybe there was an error so set
    # this variable again ...
    if ![info exists can_do_open_operation] {
	mess "You selected the Open operation a second time before the first Open was completed.\n" red
	set can_do_open_operation 1
	return 0
    }
    
    unset can_do_open_operation
    
    set nn [file_select_job open]
    if {$nn == ""} {
	set can_do_open_operation 1
	return 0
    }
    
    if {$nn != $job_name} {
	global report_summary report_point
	
	catch {unset report_summary}
	catch {unset report_point}
	
	# *** this shouldn't be done here.  There should be a
	# *** reinitialize function
	array set report_summary {
	    writesuffix .report
	    writefilename {}
	    timevalue 0.0
	    count 0
	    timetype value
	    sol_pats *
	    sol_all 0
	    writefile 0
	    writewindow 1
	    timestep 0
	}
	array set report_point {
	    writefilename {}
	    timevalue 0.0
	    timetype value
	    writefile 0
	    writewindow 1
	    timestep 0
	}
	form_kill .report_summary
	form_kill .report_point
    }
    
    if {$job_open(location) != "local"} {
	set lname $job_open(server_local_dir)/$nn
	server_read_job $nn $lname current "" \
	    "model job problem tetin_unused"
	set nn $lname
    }
    set vers $job_open(version)
    if {$vers == "(current)"} { set vers "" }
    set stat [job_load $nn $vers]
    set can_do_open_operation 1
    
    if !$stat { return 0 }
    
    if [info exists env(HOME)] {
	if [catch {open $env(HOME)/.${app_name}_file_open w} fp] {
	    user_error $fp
	    return 1
	}
	
	if {$job_open(location) == "local"} {
	    set job [list $job_open(name)]
	} else {
	    set job [list $job_open(server):$job_open(name)]
	}
	foreach v {location server name} {
	    lappend job $v $job_open($v)
	}
	set rj [lrange [ldelete $job_open(recent_jobs) $job] 0 5]
	set job_open(recent_jobs) [concat [list $job] $rj]
	
	foreach v {location server server_local_dir recent_jobs} {
	    puts $fp [list set job_open($v) $job_open($v)]
	}
	foreach v [array names file_job_server_info] {
	    puts $fp [list set file_job_server_info($v) \
			 $file_job_server_info($v)]
	}
	close $fp
    }
    return 1
}

proc file_select_job {what} {
    global app_name job_name default_job_directory job_open
    
    if ![info exists job_open(location)] {
	array set job_open {
	    location local
	    server ""
	    server_local_dir .
	    recent_jobs ""
	}
    }
    array set job_open { name "" title "" notes "" version "" }
    
    if {[info exists job_open(location)] && ($job_open(location) != "local")} {
	set def /
    } elseif {$job_name == ""} {
	set def $default_job_directory
	if {($def == "") || ![file exists $def]} { set def [pwd] }
    } else {
	set def [file dirname $job_name]
    }
    
    set prev_file [lindex [glob ~] 0]/.${app_name}_recent_jobs
    set is_m [expr {$what == "merge"}]
    return [file_selection -message "Select the project to $what." \
		-default $def \
		-title "[string totitle $what] project" \
		-get_dir 1 \
		-new_ok 2 \
		-prev_file $prev_file \
		-ok_func directory_is_job_new \
		-extra_widgets [list on_side file_job_extra_widgets $is_m] \
		-extra_widgets2 file_job_extra_widgets2 \
		-pick_func file_job_put \
		-ok_to_select "valid projects" \
		-special_list_func file_job_list_remote \
		-dir_leaf_image ${app_name}_is_job -dir_leaf_label "Project"]
}

proc file_merge {{under_part ""}} {
    global tdv_default model_container
    global job_open icepak_root job_name default_job_directory
    global group_container merge_group object_load_group object_load_list app_name
    global use_merge_transformation merge_centroid job_precision
    global rename_object_while_loading
    global expression_params expression_param_choices opt_design_var expression_param_by_cols
    
    if ![info exists job_open(location)] {
	if {[info exists env(HOME)] && \
		[file exists $env(HOME)/.${app_name}_file_open]} {
	    if [catch {source $env(HOME)/.${app_name}_file_open} res] {
		user_error $res
	    }
	}
	if {[info exists job_open(location)] && 
	    ($job_open(location) != "local")} {
	    file_job_select_server
	}
    }
    
    for {set i 0} {[info exists group_container(merge.$i)]} {incr i} {}
    set merge_group merge.$i
    
    foreach vv {
	{merge_do_trans 0}
	{merge_xoff 0}
	{merge_yoff 0}
	{merge_zoff 0}
	{merge_do_rot 0}
	{merge_axis 0}
	{merge_amount 90}
	{merge_amount_other 0}
	{merge_do_mirror 0}
	{merge_mirroraxis 2}
	{merge_mirrorhow centroid}
	{merge_do_scale 0}
	{merge_scale 1}
    } {
	set name [lindex $vv 0]
	global $name
	if ![info exists $name] { set $name [lindex $vv 1] }
    }
    
    set nn [file_select_job merge]
    
    if {$nn == ""} return
    
    set vers $job_open(version)
    if {$vers == "(current)"} { set vers "" }
    
    if {$merge_group != ""} {
	if ![info exists group_container($merge_group)] {
	    set group_container($merge_group) [model_container]
	    $group_container($merge_group) setval name $merge_group \
		obtype group
	    tree_create_group $group_container($merge_group) ""
	}
	set object_load_group $group_container($merge_group)
	mess "Adding merged objects to group \"$merge_group\"\n"
    }
    set object_load_list ""
    
    if {$vers == ""} { set pref "" } else { set pref $vers. }
    
    set use_merge_transformation 1
    set merge_centroid "0 0 0"
    
    $tdv_default configure -active 0
    
    set bad 0
    set prev_mc $model_container
    if {$under_part != ""} {
	set model_container $under_part
    }
    catch {unset rename_object_while_loading}
    set nndir [directory [list job $nn]]
    if [file exists $nndir/${pref}model] {
	if ![model_read $nndir/${pref}model 1 1] { set bad 1 }
    } elseif [file exists $nndir/geometry] {
	if ![model_read $nndir/geometry 1 1] { set bad 1 }
    } else {
	if [info exists job_version] {
	    user_error "No model or geometry file with version $job_version"
	    set bad 1
	} else {
	    user_error "No model or geometry file exists"
	    set bad 1
	}
    }
    set model_container $prev_mc
    set objlist $object_load_list
    unset object_load_list
    
    if $bad return
    
    set job_precision 0
    $tdv_default configure -active 1
    $tdv_default redraw
    
    set transform_cmds [get_transformation_cmds merge]
    
    unset use_merge_transformation
    catch {unset object_load_group}
    
    array set npts [read_array_from_problem_file $nndir/${pref}problem named_point]
    if [info exists npts(names)] {
	foreach n $npts(names) {
	    set vals ""
	    foreach v [array names npts $n,*] {
		set v2 [lindex [split $v ,] 1]
		set val $npts($v)
		switch $v2 {
		    object {
			if [info exists rename_object_while_loading($val)] {
			    set val $rename_object_while_loading($val)
			}
		    }
		}
		lappend vals $v2 $val
	    }
	    if [named_point_exists $n] {
		# Maybe the name of this point is the same as an object
		if [info exists rename_object_while_loading($n)] {
		    set n $rename_object_while_loading($n)
		}
	    }
	    if [named_point_exists $n] {
		set n [named_point_new_name_object $n]
	    }
	    
	    named_point_add_one $n $vals
	    
	    named_point_transform $n $transform_cmds
	}
	mess "Merged [llength $npts(names)] points\n"
    }
    
    # Now do the params
    set mp $nndir/${pref}problem
    array set new_expression_params [read_array_from_problem_file $mp expression_params]
    array set new_expression_param_choices [read_array_from_problem_file $mp expression_param_choices]
    array set new_expression_param_by_cols [read_array_from_problem_file $mp expression_param_by_cols]
    array set new_opt_design_var [read_array_from_problem_file $mp opt_design_var]
    
    set nnv [array size new_expression_params]
    set nov 0
    foreach v [array names new_expression_params] {
	if [info exists expression_params($v)] { incr nov }
    }
    if {$nnv && $nov} {
	set do_rename [tk_dialog .merge_params "Merge variables" "In the merged project there are $nnv design variables and $nov of them overlap with existing ones.  Do you want to share the variables or rename them?" "" -1 Share Rename]
    } else {
	set do_rename 0
    }
    foreach v [array names new_expression_params] {
	if [info exists expression_params($v)] {
	    if !$do_rename continue
	    for {set i 0} {[info exists expression_params(${v}_$i)]} {incr i} {}
	    set nv ${v}_$i
	} else {
	    set nv $v
	}
	set expression_params($nv) $new_expression_params($v)
	set expression_param_choices($nv) $new_expression_param_choices($v)
	set expression_param_by_cols($nv) $new_expression_param_by_cols($v)
	lappend opt_design_var(names) $nv
	foreach p [array names new_opt_design_var] {
	    if [string match $v,* $p] {
		set opt_design_var($nv,[lindex [split $p ,] 1]) $new_opt_design_var($p)
	    }
	}
	expression_rename_param $v $nv $objlist
	#puts "expression_rename_param $v $nv $objlist"
	mess "Renamed $v to $nv\n"
    }
    
    db_dirty mesh
    mess "Done with merge.\n"
}

proc file_job_extra_widgets {merge d} {
    global file_job_picture_label file_job_notes_text file_job_versions_list
    global app_name
    
    if [string match *pak $app_name] {
	set pages {
	    { preview Preview }
	    { info Information }
	}
	if $merge { lappend pages { trans Transformation } }
	
	set pages [form_notebook $d.nb $pages {0 0}]
	set wpreview [lindex $pages 0]
	set winfo    [lindex $pages 1]
	set wmerge   [lindex $pages 2]
	set vers 1
    } else {
	set pages {
	    { info Information }
	}
	if $merge { lappend pages { trans Transformation } }
	
	set pages [form_notebook $d.nb $pages {0 0}]
	set winfo    [lindex $pages 0]
	set wmerge   [lindex $pages 1]
	set wpreview ""
	set vers 0
    }
    
    if {$wpreview != ""} {
	form_frame $wpreview.picture flat 0 {0 0}
	$wpreview.picture configure -width 390 -height 240
	form_label $wpreview.picture.lab "(no preview available)" {0 0 -sticky news}
	set file_job_picture_label $wpreview.picture.lab
    }
    if $vers {
	form_listbox $winfo.versions Versions "" file_job_set_version "" 12x12 \
	    {0 0 -rows 3}
    }
    form_label $winfo.titlel Title {0 1}
    form_entry $winfo.title job_open(title) string {1 1}
    form_text $winfo.notes Notes job_open(notes) {2 1}
    set file_job_notes_text $winfo.notes
    set file_job_versions_list $winfo.versions
    
    if $merge {
	form_label $wmerge.tlabel "Geometric transformation" {0 0 -cols -}
	make_transform_form $wmerge merge ""
	
	form_frame $wmerge.group flat 0 {4 0 -cols - -fill none}
	form_label $wmerge.group.l "Group for merged objects:" {0 0}
	form_entry $wmerge.group.e merge_group string {0 1}
    }
    
    form_notebook_finish $d.nb
}

proc not_yet_file_job_extra_widgets2 {d} {
    global job_open server_used
    
    if {[info exists server_used] && $server_used} {
	form_radiobutton $d.local "Project on local disk" job_open(location) \
	    local {0 0 -cols -}
	form_radiobutton $d.remote "Project on remote server" job_open(location) \
	    remote {1 0 -cols -}
	form_label $d.reml "  Server" {2 0} {{job_open(location) remote}}
	futil_listentry $d.rems job_open(server) file_job_list_servers {2 1} \
	    {{job_open(location) remote}} file_job_select_server
	form_label $d.locd "  Local directory" {3 0} {{job_open(location) remote}}
	file_select_entry $d.loc job_open(server_local_dir) 1 1 \
	    "Select the local directory to keep\nprojects while they are being used." \
	    {3 1} {{job_open(location) remote}}
	
	form_rowheight $d 4 4
    }
    form_menubutton_regular $d.recent "Recently opened projects" $d.recent.menu \
	{5 0 -cols -}
    menu $d.recent.menu
    
    foreach job $job_open(recent_jobs) {
	$d.recent.menu add command -label [lindex $job 0] -command \
	    [list file_job_set_recent [lrange $job 1 end]]
    }
}

proc file_job_extra_widgets2 {d} {
    global app_name
    if ![string match *pak $app_name] { return "" }
    label $d.lab -text [form_label_text "Versions:"]
    ComboBox $d.menu -height 5 -textvariable job_open(version) \
	-modifycmd file_job_put_2 \
	-postcommand "file_job_extra_widgets2_fill_versions_menu $d.menu"
    checkbutton $d.loaduserdef -text [form_label_text "Apply user preferences from project"] -variable open_job_override_prefs
    grid $d.lab -row 0 -column 0
    grid $d.menu -row 0 -column 1
    grid $d.loaduserdef -row 1 -column 0 -columnspan 2
    
    return ""
}

proc file_job_extra_widgets2_fill_versions_menu {menu} {
    global job_open
    
    set versions [file_job_list_versions $job_open(name)]
    $menu configure -values $versions
}

proc file_job_set_recent {what} {
    global job_open file_select
    
    foreach {e v} $what {
	set job_open($e) $v
    }
    set file_select(current) $job_open(name)
    if {$job_open(location) != "local"} {
	file_job_select_server
    } else {
	file_select_update
    }
}

proc file_job_list_servers {} {
    global file_job_server_info
    
    return [concat [lsort [array names file_job_server_info]] \
		[list "" "Add server" "Modify server" "Remove server"]]
}

proc file_job_select_server {} {
    global job_open file_job_server_info
    global server_host server_port server_user server_password
    global file_select
    
    switch $job_open(server) {
	"Add server" {
	    set ans [question_box_mult .add_server "Add server" "" \
			 { { "Server name" localhost } \
			       { "Host name" localhost } \
			       { "Server port" 12345} \
			       { "User name" anonymous} \
			       { "Password" nopass} }]
	    if {$ans == ""} return
	    set file_job_server_info([lindex $ans 0]) [lrange $ans 1 end]
	    set job_open(server) [lindex $ans 0]
	}
	"Modify server" {
	    user_error "Sorry, not implemented"
	    return
	}
	"Remove server" {
	    user_error "Sorry, not implemented"
	    return
	}
    }
    
    set inf $file_job_server_info($job_open(server))
    set server_host [lindex $inf 0]
    set server_port [lindex $inf 1]
    set server_user [lindex $inf 2]
    set server_password [lindex $inf 3]
    set file_select(current) /
    file_select_update
}

# This must sort in the appropriate way and return the file names with "  "
# or "* " in front of them

proc file_job_list_remote {current dirs want_dirs sort_type} {
    global job_open
    
    if {$job_open(location) == "local"} { return __local__ }
    
    set dirs [server_list_directory $current $dirs $want_dirs $sort_type]
    if {$dirs == "__cant_connect__"} {
	set job_open(location) local
	return __local__
    } else {
	return $dirs
    }
}

# -----------------------------------------------

proc directory_is_job {dir} {
    global job_name
    
    if {[directory] != $job_name} {
	return [file exists $dir/autohex]
    } else {
	return [expr {([file exists $dir/model] && [file isfile $dir/model]) ||
		      ([file exists $dir/geometry] && [file isfile $dir/geometry])}]
    }
}

proc directory_is_job_new {dir} {
    global is_win

    if ![file exists $dir] { return 1 }
    return [expr {([file exists $dir/model] && [file isfile $dir/model]) ||
		  ([file exists $dir/geometry] && [file isfile $dir/geometry])}]
}

proc file_job_list_versions {jn} {
    if {$jn == ""} { return "" }
    
    set versions [list (current)]
    foreach f [lsort [glob_fixed $jn/*.model]] {
	lappend versions [string trim [file rootname [file tail $f]] .]
    }
    return $versions
}

proc file_job_put {jn} {
    global job_open file_job_versions_list
    
    if {$jn == ""} return
    
    set versions [file_job_list_versions $jn]
    if {[info exists file_job_versions_list] && \
	    [winfo exists $file_job_versions_list]} {
	form_listbox_set $file_job_versions_list $versions
	form_listbox_select_index $file_job_versions_list 0
    }
    
    set job_open(version) ""
    set job_open(name) $jn
    file_job_put_2
}

proc file_job_put_2 {} {
    global job_open file_job_notes_text file_job_picture_label
    
    if {$job_open(location) != "local"} {
	# Just bring the job and gif file over
	set pref $job_open(server_local_dir)/
	
	server_read_job $job_open(name) $pref$job_open(name) current "" \
	    {job image.ppm}
    } else {
	set pref ""
    }
    
    # Note that job_name, etc are not global here.
    set jd $pref$job_open(name)/job
    if {($job_open(version) != "") && ($job_open(version) != "(current)")} {
	#append jd .$job_open(version)
    }
    if [file exists $jd] {
	source $jd
	catch {set job_open(title) $job_title}
	catch {set job_open(notes) $job_notes}
    } else {
	set job_open(title) "(none)"
	set job_open(notes) "(none)"
    }
    if {[info exists file_job_notes_text] && \
	    [winfo exists $file_job_notes_text]} {
	form_text_set $file_job_notes_text $job_open(notes)
    }
    
    set pict ""
    foreach f [list .$job_open(version).gif .$job_open(version).ppm .gif .ppm] {
	set p $pref$job_open(name)/image$f
	if [file exists $p] { set pict $p; break }
    }
    
    if {[info exists file_job_picture_label] && \
	    [winfo exists $file_job_picture_label]} {
	set iml $file_job_picture_label
	if {($pict != "")} {
	    if [catch {image create photo -file $pict} im] {
		mess "$im\n" red
		return
	    }
	    set oim [$iml cget -image]
	    if {$oim != ""} { image delete $oim }
	    $iml configure -image $im
	    
	} elseif [winfo exists $iml] {
	    set im [$iml cget -image]
	    if {$im != ""} { image delete $im }
	    $iml configure -image "" -text "(no preview available)"
	}
    }
}

proc file_job_set_version {vers} {
    global job_open
    set job_open(version) $vers
    file_job_put_2
}
