proc aie_cart3d_update {} {
    global file_name cart3d cart3d_started cart3d_user_cancel

    if {![info exists cart3d_started]} {set cart3d_started 0}
    if $cart3d_started return
 
    if {(![info exists file_name(project_dir)]) || ($file_name(project_dir) == "")} {
        set file_name(project_dir) [pwd]
    }
    if {(![file exists $file_name(project_dir)]) || (![file isdirectory $file_name(project_dir)])} {
        tk_messageBox -title "Cart3D Project Error" -message "Please open a valid cart3D project first"
        set cart3d_started 0
        return
    }

    set ok [cart3d_change_projdir]
    if !$ok {
        if [info exists cart3d_user_cancel] {
            mess "Canceled by user\n"
            unset cart3d_user_cancel
        } else {
            msg ERROR "Could not change to project dir"
        }
        set cart3d_started 0
        return
    }
    cart3d_restore_guistate
    set cart3d_started 1
}

proc aie_cart3d_check_domain {} {
    global cart3d file_name

    if {[file tail $cart3d(domain_file)] == "" ||
        ![file exists $cart3d(domain_file)]} {
        if {$file_name(domain) != "" &&
            [file exists $file_name(domain)]} {
            set cart3d(domain_file) $file_name(domain)
            return 0
        }
        if [ic_uns_is_loaded] {
            msg ERROR "You must save the mesh as a domain file first."
        } else {
            msg ERROR "You must load a surface mesh first."
        }
        return 1
    }
    return 0
}

proc onMeshCart3dDEZApply { } {
    global cart3d env

    if [aie_cart3d_check_domain] return
    foreach par {file_prefix single_comp fix_normals nominal_radius \
		     num_div max_ref box_min box_max mesh_save \
		     buff_lay max_angle weight_norms mesh_internal \
		     cut_planesX cut_planesY cut_planesZ num_mgl sharp_level \
                     mesh_symX mesh_symY mesh_symZ \
		 } {
	set cart3d($par) [meshCart3dDEZ get $par]
    }

    if [info exists env(CART3D_STARS)] {
	foreach par {output_history stars_method subgrid_tol} {
	    set cart3d($par) [meshCart3dDEZ get $par]
	}
    }

    mesher_cart3d_apply
    aie_create_initial_assemblies
}

proc aie_cart3d_compute_params { } {
    global cart3d file_name
    global env tdv_default

    if [aie_cart3d_check_domain] return
    if {(![ic_uns_is_loaded]) && !([info exists stars_method] && $stars_method == 2)} {
	msg ERROR "No surface mesh loaded"
	return
    }

    foreach par {file_prefix single_comp fix_normals nominal_radius \
		     num_div max_ref box_min box_max \
		     buff_lay max_angle weight_norms mesh_internal \
		     cut_planesX cut_planesY cut_planesZ num_mgl sharp_level \
                     mesh_symX mesh_symY mesh_symZ \
		 } {
	set cart3d($par) [meshCart3dDEZ get $par]
    }
    if [info exists env(CART3D_STARS)] {
	foreach par {output_history stars_method subgrid_tol} {
	    set cart3d($par) [meshCart3dDEZ get $par]
	}
    }
    mesher_cart3d_default_inputs

    meshCart3dDEZ set box_min $cart3d(box_min)
    meshCart3dDEZ set box_max $cart3d(box_max)
    meshCart3dDEZ set finest_cell $cart3d(finest_cell)

    aie_create_initial_assemblies
    aie_create_cart3d_bounds
}

proc onMeshCart3dDEZLoad { } {
    global cart3d file_name env

    foreach par {file_prefix single_comp fix_normals nominal_radius \
		     num_div max_ref box_min box_max mesh_save \
		     buff_lay max_angle weight_norms mesh_internal \
		     cut_planesX cut_planesY cut_planesZ num_mgl finest_cell \
             sharp_level mesh_symX mesh_symY mesh_symZ} {
        if [info exists cart3d($par)] {
            set $par $cart3d($par)
        }
    }
    if [info exists env(CART3D_STARS)] {
 	    foreach par {output_history stars_method subgrid_tol} {
            set $par $cart3d($par)
        }
    }
    set prefixList ""
    foreach i [glob -nocomplain *.gui] {
        lappend prefixList [file rootname $i]
    }

    if [ic_uns_is_modified] {
	switch -- [tk_dialog .savec3dinput  "Save surface Tri Mesh" "Mesh has been modified. Do you want to save only the surface Triangle mesh?" \
		    "" -1 Yes No] {
             -1 {
                if [winfo exists .savec3dinput] { destroy .savec3dinput }
                return
            }
			0 {
			    aie_save_Mesh TRI_3
			    set cart3d(force_run_intersect) 1
			    ic_uns_set_modified 0
			}
			1 { # don't want to ask again
			    ic_uns_set_modified 0
			}
		    }
    }

    if {($file_name(domain) != $cart3d(domain_file)) || ($cart3d(force_run_intersect))} {
	ic_delete_geometry density names [ic_geo_get_objects density]
    }

    set cart3d(domain_file) $file_name(domain)
}

proc onMeshCart3dDEZAfterLoad {} {
    global cart3d_old_prjdir cart3d_started

    if {[info exists cart3d_started] && $cart3d_started == 1} {
        if {[info exists cart3d_old_prjdir] && [file isdirectory $cart3d_old_prjdir]} {
            if {$cart3d_old_prjdir != "[pwd]"} {
                catch {cd $cart3d_old_prjdir}
            }
            set found 0
            foreach f [glob -nocomplain "$cart3d(file_prefix).gui"] {
                set prefix [file rootname $f]
                if {[file exists "$prefix.i.tri"] || [file exists "$prefix.a.tri"]} {
                    set found 1
                    break
                }
            }
            if $found {
                mess "Warning: Found existing cart3D files with prefix $cart3d(file_prefix) in current\
                    project directory.\n" red
            }
        }      
    }
}

proc onMeshCart3dDEZUnload { } {
    global cart3d

    if {$file_prefix != $cart3d(file_prefix) &&
        [file exists "$file_prefix.gui"] &&
        [file exists "$file_prefix.i.tri"]} {
        set cart3d(file_prefix) $file_prefix
    }
    aie_delete_cart3d_bounds
}

proc onCartFilePrefixModify {dez val} {
    global cart3d

    if [file exists $val.gui] {
        set cart3d(file_prefix) $val
        cart3d_restore_guistate
        meshCart3dDEZ load
    }
}

proc aie_cart3d_load_mesh {} {
    global cart3d

    set dir [pwd]
    if [info exists cart3d(file_prefix)] {
        set prefix $cart3d(file_prefix)
    } else {
        set prefix "[file tail $dir]_c3d"
    }
    set fm $prefix
    foreach ext {i.tri a.tri i.triq mesh} {
        if [file exists "$fm.$ext"] {
            append fm ".$ext"
            break
        }
    }
    set fm [tk_getOpenFile -initialdir $dir -initialfile $fm \
        -title "Select Cart3d Mesh File" \
        -filetypes {{{Mesh Files} {.tri .triq .mesh}} {{All files} *}}]
    if {$fm == ""} return
    set tmpdomain ${fm}_temp.dom
    catch {cmd_rm $tmpdomain}
    if {[file extension $fm] == ".tri"} {
        set status [ic_run_c3dtri2df $fm $tmpdomain]
    } elseif {[file extension $fm] == ".triq"} {
        set status [ic_run_c3dtri2df $fm $tmpdomain 1]
    } else {
        set status [ic_run_cart3d2df $fm $tmpdomain]
    }
    if [file exists $tmpdomain] {
        if !$status {
            set opt 1
            if { [ic_uns_is_loaded] } {
                set opt [tk_dialog .unsOverwrite "Mesh Exists" \
                    "Mesh Already Exists in this File, how do you wish to proceed?" \
                    "" 1 "Merge" "Replace" "Cancel" ]
                switch -- $opt {
                    -1 {
                        if [winfo exists .unsOverwrite] { destroy .unsOverwrite }
                        cmd_rm $tmpdomain
                        return
                    } 
                    0 { }
                    1 { ic_unload_mesh }
                    default { cmd_rm $tmpdomain; return }
                }
            }
            ic_load_unstruct $tmpdomain
            aie_after_open_mesh 1 $opt
       }
       cmd_rm $tmpdomain
    }
}

proc aie_create_cart3d_bounds {} {
    global cart3d tdv_default

    aie_delete_cart3d_bounds
    set cent [tdv_get_centroid $tdv_default]

    set geo [tdv_prism_geo -color white -point1 $cart3d(box_min) \
        -point2 $cart3d(box_max)]
    $tdv_default add_image $geo
    set cart3d(img_bbox) $geo

    set cell [split $cart3d(finest_cell) x]
    set pt1 ""
    set pt2 ""
    for {set n 0} {$n < 3} {incr n} {
        set size [lindex $cell $n]
        set coord [expr [lindex $cent $n] - 0.5 * $size]
        lappend pt1 $coord
        lappend pt2 [expr $coord + $size]
    }
    set geo [tdv_prism_geo -shade solid -color white \
        -point1 $pt1 -point2 $pt2]
    $tdv_default add_image $geo
    lappend cart3d(img_bbox) $geo
}

proc aie_delete_cart3d_bounds {} {
    global cart3d tdv_default

    if [info exists cart3d(img_bbox)] {
        foreach img $cart3d(img_bbox) {
            catch {
                $tdv_default remove_image $img
                $img delete
            }
        }
        unset cart3d(img_bbox)
    }
}

proc oncart3dSolveRunLoad {} {
    global flowCart options
    global cart3d

    # run translator
    set params_file "./flowCart.par"
    set flowCart(cntl_file)  "./flowCart.cntl"
    
    mess "Running...\n"
    ic_create_flowCart_input \
	params_file $params_file \
	cntl_file   $flowCart(cntl_file) \
        faminfo_file "$cart3d(file_prefix).fam"

    set flowCart(cntl_file) flowCart.cntl
    set flowCart(restart_file) ""
    set chks [glob -nocomplain check.*]
    set latest 0
    foreach f $chks {
	set tf [file atime $f]
	if {$tf > $latest} {
	    set flowCart(restart_file) $f
	    set latest $tf
	}
    }

    foreach par {max_cycles no_fmg yaxis_span dump_fullhex gridseq_level \
		     restart_file xslices yslices zslices cmd \
		     gridseq restart dump_cutplane run_cmd } {
	if [info exists flowCart($par)] {
	    set $par $flowCart($par)
	}
    }

    foreach {w v} {gridSeqLevGI gridseq restartCompGI restart \
                   saveCutRes dump_cutplane runCmdGI run_cmd} {
        set grey [set $v]
        if {$grey == "" || !$grey} {
            ::AIEnv::GUIManagement::ToggleGrey $w 1
        } else {
            ::AIEnv::GUIManagement::ToggleGrey $w 0
        }
    }
    set run_flowcart 1
}

proc oncart3dSolveParamsLoad {} {
    solRunDEZ apply
}

proc oncart3dSolveStopLoad {} {
    solRunDEZ apply
}

proc oncart3dSolveMonitorLoad {} {
    solRunDEZ apply
}

proc onsolRunDEZApply {} {
    global flowCart options
    global cart3d

    switch $cart3dSolveEGVal {
	0 {
	    flowCart_edit_params
	}
	1 {
	    foreach par {max_cycles no_fmg yaxis_span dump_fullhex gridseq_level \
			     restart_file xslices yslices zslices cmd \
			     gridseq restart dump_cutplane run_cmd } {
		set flowCart($par) [set $par]
	    }
            if $run_flowcart {
                cart3d_solver_apply
	        aie_cart3d_visualize
            } else {
                cart3d_save_guistate
                set fp [open run_flowCart.med w]
                puts $fp [cart3d_run_flowCart_cmd]
                close $fp
            }
	}
	2 { cart3d_solver_stop }
	3 { cart3d_solver_monitor }
    }
    busy reset
}

proc aie_cart3d_visualize {} {
    global cart3d

    set triq_file $cart3d(file_prefix).i.triq
    if ![file exists $triq_file] {
	mess "Cart3D results file: \"$triq_file\" does not exist\n"
	return
    }

    # Convert triq2domain
    set domain_file "surface_results.dom"
    set status [ic_run_c3dtri2df $triq_file $domain_file 1]
    if {($status) || (![file exists $domain_file])} {
	mess "Error: Cart3D Triq -> Domain failed\n" red
	return
    }

    mess "Surface results file \"surface_results.dom\" created\n" blue
    #aie_v3p_startup files
}

proc onsolPostDEZLoad {} {
    global flowCart options
    global cart3d

    set flowCart(result_file) "$cart3d(file_prefix).i.triq"
    flowCart_update_family_info $flowCart(result_file)

    foreach par {result_file clic_outdir model_Xaxis model_Yaxis model_Zaxis} {
	if [info exists flowCart($par)] {
	    set $par $flowCart($par)
	}
    }
    set axisList [list  Xb Yb Zb -Xb -Yb -Zb]
    if [file exists $flowCart(result_file)] {
        set run_clic 1
    } else {
        set run_clic 0
    }
    solPostDEZ setdirty
}

proc onsolPostDEZApply {} {
    foreach par {result_file clic_outdir model_Xaxis model_Yaxis model_Zaxis} {
	set flowCart($par) [set $par]
    }
    flowCart_clic_apply $run_clic
    solPostDEZ setdirty
}

proc aie_cart3d_trials {} {
    aie_clear_dez
    cart3d_trials
}

proc onsolTrialsDEZLoad {} {
    global cart3d cart3d_trials flowCart

    cart3d_trials_load_trial_data

    foreach i {mach alpha} {
        set ${i}SpecifyVal $cart3d_trials(${i}Specify)
        foreach j {List 0 N D} {
            set $i$j $cart3d_trials($i$j)
        }
    }
    set beta $flowCart(beta)
    set nTrials $cart3d_trials(nTrials)
    set trials_outdir $flowCart(trials_outdir)
    set rerun $cart3d_trials(rerun)

    set componentList entire
    eval lappend componentList $flowCart(families)
    if {![info exists cart3d_trials(curgroup)] ||
         [lsearch -exact $componentList $cart3d_trials(curgroup)] < 0} {
        set cart3d_trials(curgroup) entire
    }
    set component $cart3d_trials(curgroup)

    solTrialsDEZ setdirty
}

proc oncart3dTrialsStopLoad {} {
    solTrialsDEZ apply
}

proc oncart3dTrialsResultsLoad {} {
    cart3d_trials_read_trial_data
    solTrialsDEZ apply
    solTrialsDEZ setdirty
}

proc oncart3dTrialsResultsUnload {} {
    aie_cart3d_clear_params
}

proc onCart3dComponentModify {dez val} {
    solTrialsDEZ apply
    solTrialsDEZ setdirty
}

proc onsolTrialsDEZApply {} {
    global cart3d cart3d_trials flowCart

    switch $cart3dTrialsEGVal {
        0 {
            foreach i {mach alpha} {
                set cart3d_trials(${i}Specify) [set ${i}SpecifyVal]
                foreach j {List 0 N D} {
                    set cart3d_trials($i$j) [set $i$j]
                }
            }
            if ![cart3d_trials_validate] {
                msg ERROR "Mach and/or Angle of Attack settings are invalid"
                return
            }
            cart3d_trials_get_lists
            set cart3d_trials(nTrials) [cart3d_trials_ntrials]
            solTrialsDEZ set nTrials $cart3d_trials(nTrials)
            cart3d_save_guistate
        }
        1 {
            set clic_cntl "$cart3d(file_prefix).clic.cntl"
            if ![file exists $clic_cntl] {
                msg ERROR "You must generate a clic file before running trials"
                return
            }
            set save_beta $flowCart(beta)
            set flowCart(trials_outdir) $trials_outdir
            set flowCart(beta) $beta
            set cart3d_trials(rerun) $rerun
            cart3d_trials_run
            set flowCart(beta) $save_beta
        }
        2 { uns_mon_stop }
        3 {
            set cart3d_trials(curgroup) $component
            aie_cart3d_show_params
        }
    }
}

proc onsolTrialsDEZUnload {} {
    aie_cart3d_clear_params
}

proc aie_cart3d_show_params {} {
    global cart3d_trials input_background

    set w .v.plot
    if {![winfo exists $w.res]} {
        aie_smooth_clear_histogram
        foreach ch [winfo children $w] { destroy $ch }
        set pa [frame $w.res]
        pack $pa -side left -fill both -expand 1
        set titleList [list Mach AOA CL CD CM]
        set widthList [list 8 8 8 8 8]
        set input_background white
        form_sync_listboxes $pa.reslist $titleList $widthList \
                "" 5 {0 0 -sticky nw}
        set cart3d_trials(listbox_widget) $pa.reslist
    }

    cart3d_trials_update_listbox
}

proc aie_cart3d_clear_params {} {
    global cart3d_trials

    set w .v.plot
    if [winfo exists $w.res] {
        foreach ch [winfo children $w] { destroy $ch }
        set cart3d_trials(listbox_widget) ""
    }
    cart3d_trials_clear
}

proc onsol6DOFDEZLoad {} {
    global flowCart options
    global cart3d

    if [file exists $cart3d(file_prefix).a.tri] {
	set flowCart(tri_file) $cart3d(file_prefix).a.tri
    } elseif [file exists $cart3d(file_prefix).i.tri] {
	set flowCart(tri_file) $cart3d(file_prefix).i.tri
    }

    if [info exists flowCart(tri_file)] {
	sixdof_update_file_info $flowCart(tri_file)
    }

    foreach par {tri_file sixdof_outdir model_scale dynamic_pressure \
                 gravity time_start time_step time_end store_cycle \
                 trajectory } {
    	if [info exists flowCart($par)] {
	    set $par $flowCart($par)
	}
    }
    if [info exists flowCart(surfaces)] {
	set compList $flowCart(surfaces)
    }

    if {$sixdof_outdir == ""} {set sixdof_outdir sixDOF}
    if {$model_scale == ""} {set model_scale 1.0}
    if {$dynamic_pressure == ""} {
        if {$gravity == ""} {
            set dynamic_pressure 10000.0
        } else {
            set dynamic_pressure 0
        }
    }
    if {$gravity == ""} {
        foreach dir {X Y Z} {
            set axis model_${dir}axis
            if {[info exists flowCart($axis)] &&
                [string first "Zb" $flowCart($axis)] >= 0} {
                if {$flowCart($axis) == "Zb"} {
                    lappend gravity 9.8
                } else {
                    lappend gravity -9.8
                }
            } else {
                lappend gravity 0
            }
        }
    }
    if {$trajectory == ""} {set trajectory 0}
}

proc onsol6DOFDEZApply {} {
    global flowCart options
    global cart3d

    foreach par {tri_file sixdof_outdir model_scale dynamic_pressure \
                 gravity time_start time_step time_end store_cycle \
                 trajectory } {
	set flowCart($par) [set $par]
    }
    flowCart_sixdof_apply
    busy reset
}

proc aie_sixdof_trajectory {} {
    global flowCart

    set dir [sol6DOFDEZ get sixdof_outdir]
    if {$dir == ""} {
        mess "no sixDOF output directory specified\n" red
        return
    }
    if {![file exists $dir] || ![file isdirectory $dir]} {
        if {[file tail [pwd]] == $dir} {
            set dir "."
        } else {
            mess "can't find sixDOF output directory $dir\n" red
            return
        }
    }

    set tri_file [sol6DOFDEZ get tri_file]
    set prefix [file rootname [file rootname $tri_file]]
    if {![file exists "$dir/6DOF_Moving_Comp.dat"] ||
        ![file exists "$dir/$prefix.clic.cntl"]} {
        mess "can't find 6DOF_Moving_Comp.dat and/or $prefix.clic.cntl in $dir\n" red
        return
    }

    foreach t {start step end} {
        set $t [sol6DOFDEZ get time_$t]
        if {[set $t] == ""} {
            mess "time $t not defined\n" red
            return
        }
    }

    set result_file $prefix.i.triq
    set temp_file $prefix.temp.triq
    set dom_file 6dof.temp.dom

    set cases ""
    for {set t $start} {[expr $t <= $end]} {set t [expr $t + $step]} {
        set d [format "time_%g" $t]
        if [file exists "$dir/$d/$result_file"] {
            lappend cases $d
        }
    }
    if {$cases == ""} {
        mess "no results found for specifed time range\n" red
    }

    set moving ""
    set fp [open "$dir/6DOF_Moving_Comp.dat" r]
    while {[gets $fp line] >= 0} {
        set name [lindex $line 0]
        if {$name != "" && [string index $name 0] != "\#"} {
            lappend moving $name
        }
    }
    close $fp
    if {$moving == ""} {
        mess "no moving components found\n" red
        return
    }
    mess "moving components = $moving\n"

    set comps ""
    set fp [open "$dir/$prefix.clic.cntl" r]
    while {[gets $fp line] >= 0} {
        if {[lindex $line 0] == "\$_ComponentName"} {
            set name [lindex $line end]
            if {[lsearch $moving $name] >= 0} {
                lappend comps [lindex $line 1]
            }
        }
    }
    close $fp
    if {$comps == ""} {
        mess "couldn't get component numbers for moving components\n" red
        return
    }

    if [ic_uns_is_loaded] { aie_close_Mesh }

    set count 0
    foreach d $cases {
        mess "reading results for $d\n"
        # so we can get family info
        cmd_cp "$dir/$d/$result_file" $temp_file
        ic_run_c3dtri2df $temp_file $dom_file 0 "" \
            $comps "TRAJECTORY/[string toupper $d]" $count
        if [file exists $dom_file] {
            ic_uns_load $dom_file 2 1
            cmd_rm $dom_file
            incr count
        }
    }
    cmd_rm $temp_file
    aie_after_open_mesh 1 1
    sol6DOFDEZ show
}

