
## 

proc app_bsm_generic_generate_mesh {} {
    global proc_scrib_data
    global settings 
	
    array set proc_scrib_data [::ScribApp::getDataAndProcs] 


    #
    # --> this proc will do the following commands in order
    #
    set commands "scrib_lib_export_cad_byfile"
    set skipto_num 0

    #
    # --> get files
    #
    set inputfiles ""
    if {[info exists proc_scrib_data(cad_selmethod)] && ("" != $proc_scrib_data(cad_selmethod))} {
	switch -- $proc_scrib_data(cad_selmethod) {
	    dir  {
		set extension [scrib_lib_geo_cadsys_extension_get $proc_scrib_data(cadsys)]
		set inputfiles [scrib_lib_utils_files_in_directory $proc_scrib_data(cad_dir) $extension]
	    }
	    files {
		set inputfiles $proc_scrib_data(cad_files)
	    }
	    skipto {
		set extension [scrib_lib_geo_cadsys_extension_get $proc_scrib_data(cadsys)]
		set inputfiles [scrib_lib_utils_files_in_directory $proc_scrib_data(cad_dir) $extension]
		set skipto_num $proc_scrib_data(skipto_num) 
	    }
	}
    }
    #
    # --> get working_dir and execution args
    #
    set working_dir [scrib_lib_glue_get_working_directory]
    set args        [scrib_lib_glue_get_execution_args_from_gui]
    #
    # --> execute like we mean it
    #
    #
    
    set execution_mode $proc_scrib_data(execution_mode)
    if {$execution_mode == "LOCAL"} {
    	set files [scrib_lib_exec_commands_foreach_file $commands $inputfiles $working_dir $args $skipto_num]
	} else {
     	set settings(commands) $commands
     	set settings(inputfiles) $inputfiles
     	set settings(working_dir) $working_dir
     	set settings(args) $args
     	set settings(skipto_num) $skipto_num
     	set settings(no_models) [llength $inputfiles]
     	set settings(counter) 1
 
     	app_bsm_models $inputfiles 
	}
	
    set text "Finished trying to import, mesh and export $proc_scrib_data(cadsys) files"
    stdout "\n$text:\n"
    foreach f $inputfiles { stdout "\t$f\n" }
    scrib_app_status_update $text
    #
    # --> see if the user wants to read an HTML AssemblyReport of all the meshes just generated
    #
    
    if {$proc_scrib_data(execution_mode) == "REMOTE"} {
    	if { ![info exists settings(jobsdone)] } {return}
    }
    
    if {![tk_dialog .view_xml "View mesh report" \
	      "Would you like to view a report of meshes generated for selected CAD parts?" "" 0 Yes No]} {
	
	set xml_files ""
	foreach f $inputfiles {
	    set df [file join $proc_scrib_data(wdir) [file root [file tail $f]].uns]
	    if [file exists $df] {
		set xml_file [file join $proc_scrib_data(wdir) [file root [file tail $df]].xml]
		if [file exists $xml_file] {
		    lappend xml_files "$xml_file"
		}
	    }
	}
	if {"" == $xml_files} {
	    mess "Warning: could not find any xml files to compile for report in $proc_scrib_data(wdir)\n" red
	    return
	}
	
	set desc "name of exported 'Generate mesh' command HTML report"
	set def [file join $proc_scrib_data(wdir) "generate_mesh_results_[scrib_lib_utils_date_string].html"]	
	set html_file [file_select "Select $desc" $def $desc 0 1]
	
	set args "-title \"$desc\""
	set new_html_file [scrib_lib_xml_assembly_report_write "$xml_files" XML "$html_file" HTML $args]
	if {"" == $new_html_file} {
	    mess "Warning: could not compile report for current mesh files\n" red
	    return
	}
	scrib_app_results_view $new_html_file
    }
}

## 

proc app_bsm_generic_review_mesh {} {
    global proc_scrib_data
    
    set working_dir [scrib_lib_glue_get_working_directory]
    scrib_lib_uns_remove_tempfiles $working_dir

    set skipto_num 0    
    set inputfiles ""
    set extension [scrib_lib_geo_cadsys_extension_get $proc_scrib_data(cadsys)]
    if {[info exists proc_scrib_data(cad_selmethod)] && ("" != $proc_scrib_data(cad_selmethod))} {
	switch -- $proc_scrib_data(cad_selmethod) {
	    dir  {
		set inputfiles [scrib_lib_utils_files_in_directory $proc_scrib_data(cad_dir) $extension]
	    }
	    files {
		set inputfiles $proc_scrib_data(cad_files)
	    }
	    skipto {
		set inputfiles [scrib_lib_utils_files_in_directory $proc_scrib_data(cad_dir) $extension]
		set skipto_num $proc_scrib_data(skipto_num) 
	    }
	}
    }

#    set cadfiles $inputfiles
#    foreach item $cadfiles {
#	set meshfile "[file rootname $item].uns"
#	if [file exists $meshfile] {
#	    lappend inputfiles "$meshfile"
#	} else {
#	    stdout "Warning: can't find mesh file \"$meshfile\" for cad file \"$item\"\n" red
#	}
#    }
    
    set commands "scrib_lib_uns_review_interactive"
    set exec_args [scrib_lib_glue_get_execution_args_from_gui]
    set files [scrib_lib_exec_commands_foreach_file $commands $inputfiles $working_dir $exec_args $skipto_num]
    
    set text "Finished reviewing meshed parts in med"
    stdout "\n$text:\n"
    foreach f $files { stdout "\t$f\n" }
    scrib_app_status_update $text
}

##

proc app_bsm_generic_offset_mesh {} {
    global proc_scrib_data
    #
    # --> Get working directory and clean up temp files? fixme
    #
    set working_dir [scrib_lib_glue_get_working_directory]
    scrib_lib_uns_remove_tempfiles $working_dir
    #
    # --> Make sure there is enough info for the op
    #
    if {[info exists proc_scrib_data(offset_file)] && [string equal "" $proc_scrib_data(offset_file)]} {
	stdout "cannot offset by file if not specified!\n" red
    } else {
	if ![info exists proc_scrib_data(material_mapping_file)] {
	    set proc_scrib_data(material_mapping_file) ""
	}
	scrib_lib_offset_material_mapping_write $proc_scrib_data(offset_file) $proc_scrib_data(material_mapping_file)
    }
    #
    # --> This assumes that you want to offset the uns file (file1.uns) foreach cad file (file1.tin)
    #
    set inputfiles ""
    set extension [scrib_lib_geo_cadsys_extension_get $proc_scrib_data(cadsys)]
    set cadfiles [scrib_lib_utils_files_in_directory $working_dir $extension]
    foreach item $cadfiles {
	set meshfile "[file rootname $item].uns"
	if [file exists $meshfile] {
	    lappend inputfiles "$meshfile"
	} else {
	    stdout "Warning: can't find mesh file \"$meshfile\" for cad file \"$item\"\n" red
	}
    }
    #
    # --> Foreach cad file in the directory, call this command
    #
    set commands  "scrib_lib_offset_assemble_mesh_byfile"
    set exec_args [scrib_lib_glue_get_execution_args_from_gui]
    set files [scrib_lib_exec_commands_foreach_file $commands $inputfiles $working_dir $exec_args]
    
    set text "Finished offsetting files"
    stdout "\n$text\n"
    foreach f $files { stdout "\t$f\n" }
    scrib_app_status_update $text
}

## 

proc app_bsm_generic_assemble_mesh {} {
    
    set working_dir [scrib_lib_glue_get_working_directory]
    scrib_lib_uns_remove_tempfiles $working_dir
    
    #set commands  "scrib_lib_offset_assemble_mesh_byfile"
    set exec_args [scrib_lib_glue_get_execution_args_from_gui]
    
    set script "mesh_assembly.tcl"
    set job_token [scrib_lib_exec_get_unique_job_token [file rootname $script]]
    set med_args ""
    set stat [scrib_lib_exec_medbatch $job_token "$script" $med_args $exec_args]

    
    set text "Finished assembling and welding"
    mess "\n$text.\n"
    scrib_app_status_update $text
}

## 

proc app_bsm_generic_justdoit {} {
    
    set stat 0
    if {0 != [catch {app_bsm_generic_generate_mesh} res]} {
	stdout "There may have been problems in generating the mesh:\n$res\n" red
	incr stat
    }
#    if {0 != [catch {app_bsm_generic_offset_mesh} res]}  {
#	stdout "There may have been problems in offsetting the mesh:\n$res\n" red
#	incr stat
#    }
    if {0 != [catch {app_bsm_generic_assemble_mesh} res]}  {
	stdout "There may have been problems in assembling the mesh:\n$res\n"
	incr stat
    }
    
    scrib_app_status_update "Finished doing all steps"

    return $stat
}

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

##

proc app_compute_bolt_hole_dia {val} {

    global proc_scrib_data

        

    if [info exists proc_scrib_data(ratio_rings)] {
	set ratio $proc_scrib_data(ratio_rings)
    } else { 
	set ratio 0.6
    }
    if [info exists proc_scrib_data(number_rings)] {
	set Nr $proc_scrib_data(number_rings)
    } else { 
	set Nr 2
    }
    if [info exists proc_scrib_data(mesh_size)] {
	set Msize $proc_scrib_data(mesh_size)
    } else { 
	set Msize 10
    }

     if [info exists proc_scrib_data(Fudge)] {
	set Fudge $proc_scrib_data(Fudge)
	# Note: Fudge does not currently exist in the GUI, but may be added later.
         #           The Fudge factor exists because the equation would otherwise predict the one optimal diameter, but we want a range.
         #           Seting a Fudge factor above 1 allows us to have a range of sizes above optimal.
         #           When time permits, I will make up a way to optimise this so that the optimal size apears in the middle of each range.
    } else { 
	set Fudge 1.25
    }
    
    set Pi 3.14159265359
    set Ne $val
    set w2w1 [expr 1.0+$ratio*sin(2*$Pi/$Ne)]
    return [expr round($Ne * $Msize * pow(( 1 / $w2w1), $Nr) * $Fudge / $Pi) ]

}

##

proc app_compute_fillet_length {nodes} {

    global proc_scrib_data

    if [info exists proc_scrib_data(mesh_size)] {
	set Msize $proc_scrib_data(mesh_size)
    } else { 
	set Msize 10
    }
    
    if [info exists proc_scrib_data(Fudge2)] {
	set Fudge2 $proc_scrib_data(Fudge2)
	# Note: Fudge2 does not currently exist in the GUI, but may be added later.
	#           The Fudge factor exists so I can tweak this setting later.
	#           Seting a Fudge2 factor below 1 means that fillet mesh will be finer than average mesh.
	#           Currently I have it set to 1, which means that the size of elements on the fillet should 
	#           not exceed the overall mesh size setting. 
    } else { 
	set Fudge2 0.75
    }
    
    return [expr round($Msize * ($nodes-1) * $Fudge2) ]       
}

proc app_bsm_generic_view_results_report {} {
    global proc_scrib_data
    
    if ![info exists proc_scrib_data(results_report)] {
	mess "Error: cannot find result report information\n" red
	return 0
    } elseif ![file exists $proc_scrib_data(results_report)] {
	mess "Error: cannot find file \"$proc_scrib_data(results_report)\" from which to load results report\n" red
	return 0
    }
    
    scrib_app_results_view $proc_scrib_data(results_report)
}


# This checks at every 10 secs and run the test top in the queue
# for all the run_hosts
proc check_run_queue {} {
    global settings bsm_queue
    global job_running
                                                                                                                 
    set model_dir $settings(model_dir)
    set working_dir $settings(working_dir)
#
    set all_done 1

    foreach host $settings(run_hosts) {
    set settings(running_file,$host) [file join $working_dir $host-is-busy]
    set settings(finish_file,$host) [file join $working_dir $host-is-done]
    
    if [file exists $settings(running_file,$host)] {set all_done 0}
    }
#


        set model_to_run [lindex $settings(remaining_model) 0]



        set list_free_host [get_free_hosts] 
        set free_host [lindex [get_free_hosts] 0]
              mess "Model to run: $model_to_run\n" red     
    
        if {$settings(remaining_model) != ""} {
            set all_done 0
	    
           if {$list_free_host != ""} {
                if [catch {start_server_client $free_host $model_to_run} res] {
                    mess "$res\n" red
                    set settings(remaining_model) $settings(remaining_model)
                }
                  mess "Model: $model_to_run: started\n" blue
                  mess "Remaining models: $settings(remaining_model)\n"      
                  set settings(remaining_model) [lrange $settings(remaining_model) 1 end]
         
            }
        }

    if {!($all_done)} {
        mess "Not all done: \n" blue
        after 3000 check_run_queue 
    } else {
        mess "All Models Done\n"
	set settings(jobsdone) 1
	#app_bsm_generic_generate_mesh
#
# Copy the final result in Phoenix
#
    }
}
                                                                                                                 

proc get_model_to_run {host} {
    global bsm_queue
                                                                                                                 
    return [lindex $bsm_queue($host) 0]
}

proc app_bsm_models {models} {
    global env
    global settings
    global bsm_queue
    global proc_scrib_data 



    if ![info exists proc_scrib_data(dir)] {
   	 if [info exists proc_scrib_data(wdir)] {
        	set proc_scrib_data(dir) $proc_scrib_data(wdir)
    	 } else {
        	set proc_scrib_data(dir) [pwd]
    	 }
     }
                                                                                                                 
    set model_dir $proc_scrib_data(dir) 
    set settings(model_dir) $model_dir                                                                                                                 
    set run_mode $proc_scrib_data(run_type) 
    set settings(run_mode) $run_mode

#    set run_mode [::ScribApp::scrib_app_scrib_data_get run_type]

    if {$run_mode == "batch"} {
        set settings(mode) {-4 -batch}
        mess "GUI MODE: BATCH\n"
       set gui_mode batch
   } else  {
        set settings(mode) ""
        set gui_mode interactive
    }
     if {( $gui_mode == "interactive") && ($proc_scrib_data(disp_mc_name) == "")} {
       mess "GUI MODE: Interactive\n Please set the display machine name\n" red
       return
     }
    set settings(display_mc_name) $proc_scrib_data(disp_mc_name)
                                                                                                                 
    set settings(lic_file) $proc_scrib_data(set_icem_lic_file)
       if {$proc_scrib_data(set_icem_lic_file) == ""} {
         mess "Please set the license file \n" red
         return
       }
    mess "LM_LICENSE_FILE: $settings(lic_file)\n"
       if {[::ScribApp::bsm_get_plats] == ""} {
        mess "ICEM_ACN is not set for any platforms\n" red
       return
       }
    set settings(run_hosts) ""
    foreach plat [::ScribApp::bsm_get_plats] {
        set var1 set_icem_acn_${plat}
        set var2 set_remote_mc_${plat}
        foreach remote_host [::ScribApp::scrib_app_scrib_data_get $var2] {
            if {[::ScribApp::scrib_app_scrib_get_value $var1] && [::ScribApp::scrib_app_scrib_get_value $var2]} {                                                                                                                 
                set settings(icem_acn_var,$remote_host) [::ScribApp::scrib_app_scrib_data_get $var1]
                mess "$remote_host, ICEM_ACN: $settings(icem_acn_var,$remote_host)\n"
                lappend settings(run_hosts) $remote_host
                set bsm_queue($remote_host) ""
            }
        }
    }
                                                                                                                 
    set settings(run_tests) ""
    set settings(remaining_hosts) $settings(run_hosts) 
    set settings(remaining_model) $models 
    set n 0
    set total_n_tests [llength $models]
    set n_hosts [llength $settings(run_hosts)]  
                                                                                                                 
    check_run_queue 
}


proc get_free_hosts {} {
    global job_running
    global settings
    set free_hosts ""
    set hosts $settings(run_hosts)
 
    foreach host $hosts {                                                                                                
     set running_stat $settings(running_file,$host) 

    	if [file exists $running_stat] {
        	set free 0
    	} else {
        	set free 1
             lappend free_hosts $host
    	}
     } 
    return $free_hosts
}

proc start_server_client {host model} {
    global env
    global settings socket_info
    global job_running
    global bsm_queue

    set model_dir $settings(model_dir)
    set working_dir $settings(working_dir) 

    set job_running($host) 1
    set model_running($model) 1
    set server_setup_file [file join $env(ICEM_SCRIB) lib srver.tcl]

    if {[::ScribApp::is_plat_win]} { 
         set settings(tmp_dir) [file join $env(HOME) "Local Settings" Temp]
     } else {
         
         set settings(tmp_dir) /tmp
     }
     
     set server_setup_cp_file [file join $settings(tmp_dir) srver.tcl]  
 

    if  {[info exists env(ICEM_USE_SSH)] && $env(ICEM_USE_SSH) } {                                                                                                                     
       if {![file exists $host:$server_setup_cp_file]} {
           if [catch {exec scp $server_setup_file $host:$settings(tmp_dir)} err_msg] {
              mess "$err_msg\n" red
           }
                                                                                                                
       }
    } else {
       if {![file exists $host:$server_setup_cp_file]} {
           if [catch {exec rcp $server_setup_file $host:$settings(tmp_dir)} err_msg] {
              mess "$err_msg\n" red
           }
                                                                                                                
       }    
    }
                                                                                                                
    set socket_info(port,$host)  [get_server_client_sock $host]
    mess  "cd $settings(working_dir); setenv DISPLAY $settings(display_mc_name):0; setenv ICEM_ACN $settings(icem_acn_var,$host); setenv LM_LICENSE_FILE $settings(lic_file); $settings(icem_acn_var,$host)/bin/icemcfd $settings(mode) -script $server_setup_cp_file  port $socket_info(port,$host) \n"
                    
    if  {[info exists env(ICEM_USE_SSH)] && $env(ICEM_USE_SSH) } {
	    if {[info exists env(SHELL)] && $env(SHELL)=="/bin/bash" || $env(SHELL)=="/bin/ksh"} {   
	        if [catch {exec ssh $host "cd $settings(working_dir); export DISPLAY=$settings(display_mc_name):0; export ICEM_ACN=$settings(icem_acn_var,$host); export LM_LICENSE_FILE=$settings(lic_file); $settings(icem_acn_var,$host)/bin/icemcfd $settings(mode) -script $server_setup_cp_file  port $socket_info(port,$host)" &} res] {
        	    mess "Error: $res\n" red
        	    set job_running($host) 0
        	    return
    	        }
	    } else {
	        if [catch {exec ssh $host "cd $settings(working_dir); setenv DISPLAY $settings(display_mc_name):0; setenv ICEM_ACN $settings(icem_acn_var,$host); setenv LM_LICENSE_FILE $settings(lic_file); $settings(icem_acn_var,$host)/bin/icemcfd $settings(mode) -script $server_setup_cp_file  port $socket_info(port,$host)" &} res] {
        	    mess "Error: $res\n" red
        	    set job_running($host) 0
        	    return
    	        }	    
	    }
		
	       
	       
	} else {                                                                                       
    	    if [catch {exec rsh $host "cd $settings(working_dir); setenv DISPLAY $settings(display_mc_name):0; setenv ICEM_ACN $settings(icem_acn_var,$host); setenv LM_LICENSE_FILE $settings(lic_file); $settings(icem_acn_var,$host)/bin/icemcfd $settings(mode) -script $server_setup_cp_file  port $socket_info(port,$host)" &} res] {
        	mess "Error: $res\n" red
        	set job_running($host) 0
        	return
    	    }
	}
                                                                                                                
    set maxwait [expr 60*1000]
    set settings(running_file,$host) [file join $settings(working_dir) $host-is-busy]                                                                                                            
    set socket_info(socket,$host) ""
    after 1000 check_start $host $socket_info(port,$host) $model
}

proc run_model {host model} {
    global proc_scrib_data env
    global settings socket_info
    global bsm_queue

  
    set model_dir $settings(model_dir)
    set working_dir $settings(working_dir)
    # mess "Running model: \#$model_num on $host...\n"
                                                                                                                
    set sock $socket_info(socket,$host)

    set settings(finish_file,$host) [file join $working_dir $host-is-done]
                                                                                                                
    set exportformat [string totitle $proc_scrib_data(export)]
    set exportfile [scrib_lib_export_filename_get $proc_scrib_data(export_dir) $model \
                        $proc_scrib_data(export_extension)]

    scrib_lib_utils_record_append "------------------------------------\
            ---------------------------\n \
            Meshing file $model in ICEM CFD for export to $proc_scrib_data(export)\n"

    set proc_scrib_data(model) $model

    set override_use_script ""
    set med_args ""
    set custom_script ""
    set logdir .

    set exec_args [scrib_lib_glue_get_execution_args_from_gui]
    
     if ![info exists proc_scrib_data(foreach_script_name)] {
        set script "mesh_quad.tcl"
        set script2 "mesh_tetra.tcl"
    } else {
        set script $proc_scrib_data(foreach_script_name)
    }
    if ![info exists proc_scrib_data(foreach_script_name2)] {
        set script2 "mesh_tetra.tcl"
    } else {
        set script2 $proc_scrib_data(foreach_script_name2)
    }
 
    set job_token [scrib_lib_exec_get_unique_job_token [file tail [file root $model]]]
 
    set base_script $script
 
        set custom_script [file join "$logdir" ${job_token}_med_script.tcl]


      set script [scrib_lib_exec_build_medscript "$script"  $custom_script]
      set script [pwd]/[lindex [split $script /] 1]
  
    
#    set text "Finished assembling and welding"
#    mess "\n$text.\n"
#    scrib_app_status_update $text
    
    
                                                                                                        
    puts $sock "source $script"
    flush $sock
                                                                                                                
    after 1 check_finish $host $sock $model 
}

proc check_start {host port model} {
    global socket_info
    global job_running
    global bsm_queue settings
    set working_dir $settings(working_dir)
    set t 0
       if ![catch  {socket $host $port} sock] {
        set socket_info(socket,$host) $sock
        fconfigure $sock -buffering line -blocking 0
        fileevent $sock readable [list svcHandler $sock $host]
       
        set running_file [open $settings(running_file,$host) w]                                                                           
        mess "successfully connected to host: $host\n" blue
        run_model $host $model
       } elseif {$socket_info(socket,$host) == ""} {
         after 1000 "check_start $host $port $model"
       }  
}

#
# this is a synchronous connection:
# The command does not return until the server responds to the
#  connection request

proc get_server_client_sock { eshost } {
        if [catch {socket -server $eshost 0} sock] {
                puts "couldn't open server socket"
        } else {
                set sport [fconfigure $sock -sockname]
                set esport [lindex $sport 2]
                close $sock
        }
        puts "esport: $esport"
       return $esport
}

#
proc check_finish {rh sock model} {
    global job_running common_tree_data
    global bsm_queue settings
    global env
    set host $rh

    set finish_file $settings(finish_file,$host)
    set running_file $settings(running_file,$host)
    set working_dir $settings(working_dir)
    set model_dir $settings(model_dir)
        
                                                                     
       if {[file exists $finish_file] && (![file exists $running_file])} {
        set wait 0
        after 5000 "set wait 1"
        vwait wait
                                                                                
            	if [ catch {close $sock} res] {
           	 mess "$res\n" red
        	}
                                                                                
        mess "job on $host finished normally\n"
        set job_running($host) 0
	exec rm $finish_file
                                                                                
        } else {
        after 5000 "check_finish $host $sock $model"
       } 
}

proc svcHandler {sock host} {
    global job_running
    global socket_info settings

    set line [gets $sock]    ;# get the server packet
    if {[eof $sock]} {    ;# server gone or finished
        #close $sock        ;# release the servers client channel
        #set job_running($host) 0


    } else {
        mess "$line\n"
        #set socket_info(socket,$host) $sock
       if {$line == "Job Complete" || $line == "Job Failed"} {
       	 if [file exists $settings(running_file,$host)]  {exec rm $settings(running_file,$host) }
		 exec touch $settings(finish_file,$host)
	 	 puts $sock "exit"

	}	
	
	
    }
}

proc read_sock {sock} {
    global socket_info

    set host [lindex [fconfigure $sock -peername] 1]
    mess "Established connection to host $host\n"
    set socket_info(socket,$host) $sock
}


