
# This code creates the user interface for tetra.
#
# Copyright (c) 1993 - 1995 Pacific Marketing and Consulting, Inc,
#       and ICEM Systems, GmbH.  All rights reserved.
# Author:  Wayne A. Christopher, wayne@icemcfd.com

proc modify_load_mesh {} {
    global cut_domain mesh_dirty config_dir cut_domain_in_import
    
    if [info exists mesh_dirty] modify_save_mesh
    if [select_cut_domain 1] {
	set d domains; if $cut_domain_in_import { set d import }
	reload_leo_domain $config_dir($d)/$cut_domain 1 1
    }
    
    print_family_stats
    
    catch {unset mesh_dirty}
}

proc modify_save_mesh {} {
    global cut_domain mesh_dirty config_dir families mesh_family_active
    global cut_domain_in_import boco_modified tetin_merge_pid last_line
   
    if [info exists tetin_merge_pid] {
	foreach mesh [array names tetin_merge_pid] {
	    set pid $tetin_merge_pid($mesh)
	    command "write_tetra_domain $mesh $pid \{BAR_2 TRI_3 QUAD_4\}"
	}
	catch {unset mesh_dirty}
	cmd_rm $config_dir(domains)/tetin_merge
	return
    }
    
    if [select_cut_domain 0] {
	set fams ""
	set mess "Save what families?  (Note: if you save only the visible\
		families, the triangles but not the tetras will be written.)"
	if [tk_dialog .all "Save mesh" $mess "" -1 \
		"All families" "Visible families"] {
	    foreach f $families {
		if $mesh_family_active($f) { lappend fams $f }
	    }
	    set types "BAR_2 TRI_3 QUAD_4"
	} else {
	    command lte_check_invalid_tets
	    set mm ""
	    if $last_line {
		set mm "  (Note that the volume and surface meshes are\
			inconsistent.)"
	    }
	    switch [tk_dialog .all "Save mesh" "Which elements?$mm" "" -1 \
		    "Surface" "Volume"] {
		0 { set types "BAR_2 TRI_3 QUAD_4" }
		1 { set types "BAR_2 TRI_3 QUAD_4 TETRA_4 PYRA_5 PENTA_6 HEXA_8" }
	    }
	}
	if $cut_domain_in_import {
	    set ddir import
	} else {
	    set ddir domains
	}
	command "write_tetra_domain $config_dir($ddir)/$cut_domain \
		\{$fams\} \{$types\}"
	catch {unset mesh_dirty}
	
	if [info exists boco_modified] {
	    mess "Writing out modified boco file\n"
	    boco_save $config_dir(mesh)/boco
	}
    }
}

proc print_family_stats {} {
    global families family_count
    
    mess "\nFamily\tpid\tcount\n" orange
    set total 0
    foreach f $families {
	set n $f
	if [info exists family_count($f)] {
	    set c $family_count($f)
	} else {
	    set c 0
	}
	mess "$n\t$f\t$c\n" orange
	incr total $c
    }
    mess "\ttotal\t$total\n" orange
}

proc modify_list_families {} {
    global families family_number_of_name cad_family_active
    
    set fams ""
    foreach f $families {
	set n $f
	if {[info exists cad_family_active($f)] && $cad_family_active($f)} {
	    lappend fams $n
	}
	set family_number_of_name($n) $f
    }
    return $fams
}

proc set_phase_modify {in} {
    global tetra_leo_bin cut_domain env config_dir tetin_file mesh_dirty
    global current_phase process_ident cut_domain_in_import
    global set_phase_modify_auto has_tetin tetin_merge_pid use_xwindows
    global single_buffer
    
    if $in {
	if {![info exists process_ident] || ($process_ident != "leo")} {
	    if {![info exists cut_domain] && \
		    [file exists $config_dir(domains)/cut_domain.1]} {
		set cut_domain cut_domain.1
	    }
	    if ![info exists set_phase_modify_auto] {
		if ![select_cut_domain 1] return
		
		if $cut_domain_in_import {
		    set ddir $config_dir(import)
		    set imp 1
		} else {
		    set ddir $config_dir(domains)
		    set imp 0
		}
	    } else {
		set ddir $config_dir(domains)
		set imp 0
	    }
	    
	    set env(LEO_TETRA) 1
	    if $single_buffer {
		set args "-single_buffer"
	    } else {
		set args ""
	    }
	    start_process leo .v.view $tetra_leo_bin leo% 0 $args
	    
	    if {$imp && ![info exists tetin_merge_pid]} {
		command "set all_pids_value 0" 0
	    }
	    reload_leo_domain $ddir/$cut_domain 1 1
	    
	    if {$has_tetin && ($tetin_file != "")} {
		busy 1
		command "cad_load_tetin $config_dir(mesh)/$tetin_file 0"
		update_display surf
		busy 0
	    }
	    catch {unset mesh_dirty}
	}
	disable_stuff 1
    } else {
	if {$current_phase == "mesher"} {
	    if [info exists mesh_dirty] modify_save_mesh
	    finish_process
	    
	    disable_stuff 0
	    
	    # May as well do this here ...
	    set tmps [glob -nocomplain $config_dir(domains)/__temp_*]
	    if {$tmps != ""} { eval cmd_rm -f $tmps }
	}
    }
}

proc select_cut_domain {load} {
    global config_dir cut_domain cut_domain_in_import tetin_file env
    global tetin_merge_pid has_tetin tetin_merge_name has_tetin
    
    set do_merge_tetin 0
    
    if $load {
	set has_imp [expr {[glob -nocomplain $config_dir(import)/*] != ""}]
	set has_tetin [expr {[glob -nocomplain $config_dir(mesh)/tetin*] != ""}]
	
	set mess "You can edit a mesh in the domains directory, the import\
directory, or all the surfaces in a tetin file produced by unput.  Please\
select one:"
	switch [tk_dialog .in_import "Mesh location" $mess "" -1 \
		    domains import tetin] {
			0 {
			    set cut_domain_in_import 0
			    set ddir $config_dir(domains)
			}
			1 {
			    set cut_domain_in_import 1
			    set ddir $config_dir(import)
			}
			2 {
			    set cut_domain_in_import 1
			    set ddir $config_dir(import)
			    set do_merge_tetin 1
			}
		    }
    
    } else {
	if $cut_domain_in_import {
	    set ddir $config_dir(import)
	} else {
	    set ddir $config_dir(domains)
	}
    }
    
    if $do_merge_tetin {
	set cut_domain tetin_merge
	
	# First pull out all the unstruct_meshes from the tetin file.
	
	set files ""
	foreach f [glob -nocomplain $config_dir(mesh)/tetin*] {
	    set ff [file tail $f]
	    lappend files $ff
	}
	set mess "Please select a tetin file for the mesh."
	set ff [choose_one $mess $files tetin1 +300+300]
	set from_tetin $config_dir(mesh)/$ff
	set tetin_file ""
	
	set dom_list dom_list_tmp
	set dfp [open $dom_list w]
	set fp [open $from_tetin r]
	set next 0
	set nsurfs 0
	while {![eof $fp]} {
	    set line [gets $fp]
	    switch -glob $line {
		define_surface* {
		    set nn 0
		    set pname $nsurfs
		    foreach ww $line {
			if $nn {
			    set pname $ww; break
			} elseif [string match name $ww] {
			    set nn 1
			}
		    }
		    set next 1
		}
		unstruct_mesh* {
		    if $next {
			set mesh [lindex $line 1]
			if ![string match */* $mesh] {
			    set mesh $config_dir(import)/$mesh
			}
			puts $dfp $mesh
			incr nsurfs
			set tetin_merge_pid($mesh) $nsurfs
			set tetin_merge_name($nsurfs) $pname
			set next 0
		    }
		}
		default { set next 0 }
	    }
	}
	close $fp
	close $dfp
	
	if !$nsurfs {
	    error "There are no unstructured mesh surfaces in the tetin file."
	}
	
	# Now run merge_unstr to get a single mesh.
	set merge $env(ICEM_ACN)/icemcfd/merge_unstr
	mess "Running merge_unstr on $nsurfs surfaces ...\n"
	set out [exec $merge -reset_pids -dom_list $dom_list \
		     $config_dir(import)/$cut_domain]
	mess $out\n blue
		
	set has_tetin 0
	return 1
	
    } else {
	catch {unset tetin_merge_pid}
	
	if [info exists cut_domain] { set def $cut_domain } else { set def "" }
	
	set files ""
	foreach f [glob -nocomplain $ddir/*] {
	    set ff [file tail $f]
	    if [string match __temp_* $ff] continue
	    lappend files $ff
	}
	if {$files == ""} {
	    mess "Error: no domain files available\n" red
	    return 0
	}
	if $load {
	    set mess "Please select a domain to edit.  You can delete\
		domain files using the \"Delete\" button once you have\
		selected them."
	} else {
	    set mess "Please select a file to save the domain to.  You can delete\
		domain files using the \"Delete\" button once you have\
		selected them."
	}
	set ff [choose_one $mess $files $def +300+300 delete_cut_domain]
	if {$ff != ""} {
	    set cut_domain $ff
	    
	    if {$load && !$cut_domain_in_import} {
		set files ""
		foreach f [glob -nocomplain $config_dir(mesh)/tetin*] {
		    set ff [file tail $f]
		    lappend files $ff
		}
		if {$files == ""} {
		    set tetin_file ""
		} else {
		    if ![file exists $config_dir(mesh)/$tetin_file] {
			set tetin_file ""
		    }
		    set mess "Please select a tetin file for the mesh.  Cancel\
                       means to load in no tetin file."
		    set ff [choose_one $mess $files $tetin_file +300+300]
		    set tetin_file $ff
		}
	    }
	    set has_tetin 1
	    return 1
	} else {
	    set has_tetin 0
	    return 0
	}
    }
}

proc select_uncut_and_cut_domain {} {
    global config_dir cut_domain uncut_domain
    
    if [info exists uncut_domain] { set def $uncut_domain } else { set def "" }
    
    set files ""
    foreach f [glob -nocomplain $config_dir(domains)/*] {
	lappend files [file tail $f]
    }
    if {$files == ""} {
	mess "Error: no domain files available\n" red
	return 0
    }
    set mess "Please select an uncut domain to edit.  You can delete\
	    domain files using the \"Delete\" button once you have\
	    selected them."
    set ff [choose_one $mess $files $def +300+300 delete_cut_domain]
    if {$ff == ""} { return 0 }
    set uncut_domain $ff
    
    if 0 {
	if [info exists cut_domain] { set def $cut_domain } else { set def "" }
	set mess "Please select a cut domain, which will be the output of the\
		cutter, or enter a new domain name.  You can delete\
		domain files using the \"Delete\" button once you have\
		selected them."
	set ff [choose_one $mess $files $def +300+300 delete_cut_domain]
	if {$ff == ""} { return 0 }
	set cut_domain $ff
    }
    
    return 1
}

proc delete_cut_domain {name} {
    global config_dir cut_domain_in_import
    
    if $cut_domain_in_import {
        set path $config_dir(import)/$name
    } else {
        set path $config_dir(domains)/$name
    }
    
    set mess "Delete domain file \"$path\"?"
    if ![tk_dialog .delfile "Delete file" $mess "" -1 "Yes" "No"] {
	cmd_rm -f $path
	return 1
    }
    return 0
}

proc run_mesh_filter {command before_dom after_dom} {
    busy 1
    cmd_rm -f $before_dom $after_dom
    
    command "write_tetra_domain $before_dom" 0
    
    if ![file exists $before_dom] {
	mess "Domain not written\n" red
	return
    }
    puts $command
    set output [eval exec $command]
    mess "$output\n" orange
    busy 0
    
    if [file exists $after_dom] {
	reload_leo_domain $after_dom 1
    } else {
	mess "Domain not reloaded\n" red
    }
    cmd_rm -f $before_dom $after_dom
}

proc reload_leo_domain {dom verbose {init 0}} {
    global types_loaded last_line mesh_dirty display_flag

    busy 1
    if $verbose { mess "Reloading domain ...\n" }
    command "view_active 0" 0
    command "reload_tetra_domain $dom [expr {!$verbose}]" 0
    if {$last_line == ""} {
	mess "Domain not loaded.\n" red
	busy 0
	return 0
    }
    set types_loaded $last_line
    add_families
    if $init {
	set display_flag(face) 1
	set display_flag(edge_single) 1
	set display_flag(edge_multiple) 1
    }
    update_display face
    command "view_active 1" 0
    if $verbose { mess "Done.\n" }
    set mesh_dirty 1
    if $init { command "reset_view" }
    busy 0
    return 1
}

proc ensure_cad_surface_exists {} {
    global tetra_domains cad_objects
    
    if {![info exists cad_objects] || ($cad_objects == "")} {
	puts "No CAD surface defined -- using starting mesh for projection."
	set domfile [[lindex $tetra_domains 0] get -filename]
	set obj [bspline_object -domain_file $domfile -surface 1]
	$obj compute
	set cad_objects $obj
    }
}

proc parallel_to_elem {} {
    global last_line
    
    banner "Pick the element with the left button."
    command "select_stuff elem 1 mesh_pickable" 0
    banner ""
    if {$last_line == ""} return
    set set [lindex [lindex $last_line 0] 0]
    set num [lindex [lindex $last_line 0] 1]
    command "orient_element [lindex $last_line 0]"
}
