proc ICC_gateway_dirs {} {
    lappend dirs ICCGateway/CNext/resources/msgcatalog
    lappend dirs ICCGateway/CNext/code/dictionary
    lappend dirs ICCGateway/ICCGatewayCatalog.m/src
    lappend dirs ICCGateway/ICCGatewayBC.m/LocalInterfaces
    lappend dirs ICCGateway/ICCGatewayBC.m/src
    lappend dirs ICCGateway/ICCGatewayWB.m/src
    
    foreach d $dirs {
	catch {file mkdir $d}
    }
}

#
# Use the boco info to create template substituted code for both
# the CATIA catalog and the CATIA menu bars
#
proc ICC_gateway_catalog {{solver ""}} {
    global gateway_categories gateway_bcs gateway_pars basicComponents
    
    ICC_gateway_dirs
    catch {unset basicComponents}
    if {$solver != ""} {
	ICC_gateway_solverscheme $solver dummy.scm
    }
    
    set fp [open ICCGatewayCatalog_template.cpp]
    set file [read $fp]
    close $fp
    
    set allnames [array names gateway_bcs]
    foreach name $allnames {
	set nl $gateway_bcs($name)
	set codelines [ICC_emit_to_catalogcode $name $nl]
	if {$codelines != ""} {
	    append code "${codelines}\n"
	}
    }
    regsub __BCS__ $file $code result
    
    set fp [open ICCGateway/ICCGatewayCatalog.m/src/ICCGatewayCatalog_new.cpp w]
    puts $fp $result
    close $fp
}

proc ICC_emit_to_catalogcode {name bc} {
    global basicComponents gateway_categories
    set nl [llength $bc]
    
    if [ICC_check_for_MD $name] {
	return ""
    }
    
    # just a label if no sub fields
    
    puts "processing $name"
    set code "\tnextCompName = \"ICCCFD${name}\";\n"
    append code "\tnextRestraintName = \"ICCCFD${name}Restraint\";\n"
    append code "\tpNextEntity = 0;\n"
    append code "\trc = CATSamCatalogFactory::CreateAnalysisEntity(\\\&nextRestraintName, \\\&AnalRestraint, \\\&pNextEntity, \\\&piCatalog, publicSpec, derivable);\n";
    append code "\tif (!pNextEntity) \{\n"
    append code "\t\tcout << \"Failed to create SU for $name\" << endl;\n"
    append code "\t\tpiCatalog->Release(); piCatalog = 0;\n"
    append code "\t\treturn 3;\n"
    append code "\t\}\n"
    if {$nl == 0} {
	# append code "\tnextPhysType = \"CFD_LABEL_RESTRAINT\";\n"
	append code "\tnextPhysType = \"IMPORTED_RESTRAINT\";\n"
	append code "\tCATSamCatalogFactory::SetPhysicalType(pNextEntity, \\\&nextPhysType);\n"
	append code "\tspParm = spCkeFact->CreateString(\"BC Name\", \"$name\");\n"
	append code "\tif (spParm == NULL_var) \{\n"
	append code "\t\tcout << \"Failed to create SU for $name\" << endl;\n"
	append code "\t\tpiCatalog->Release(); piCatalog = 0;\n"
	append code "\t\treturn 3;\n"
	append code "\t\}\n"
	append code "\tspParm->QueryInterface(IID_CATICkeParm, (void **) \\\&pParm);\n"
	append code "\tif (!pParm) \{\n"
	append code "\t\tcout << \"Failed to create SU for $name\" << endl;\n"
	append code "\t\tpiCatalog->Release(); piCatalog = 0;\n"
	append code "\t\treturn 3;\n"
	append code "\t\}\n"
	append code "\tCATSamCatalogFactory::SetBasicComponent(0, pNextEntity, \\\&piCatalog, pParm);\n"
	append code "\tpParm->Release(); pParm = 0;\n"
    } else {
	set col 1
	append code "\tnextPhysType = \"IMPORTED_RESTRAINT\";\n"
	append code "\tCATSamCatalogFactory::SetPhysicalType(pNextEntity, \\\&nextPhysType);\n"
	append code "\tnextSU = \"SAMBindingComponent\";\n"
	append code "\tpAggrField = 0;\n"
	set var ICCCFD${name}
	if ![info exists basicComponents($var)] {
	    set basicComponents($var) 1
	    # append code "\tCATSamCatalogFactory::SetBasicComponent(\\\&nextRestraintName, pNextEntity, \\\&piCatalog);\n"
	    append code "\tCATSamCatalogFactory::CreateBasicComponent(\\\&nextCompName, \\\&nextSU, \\\&pAggrField, \\\&piCatalog);\n"
	} else {
	    error "Duplicate component entry"
	}
	append code "\tspObjAccess = pAggrField;\n"
	append code "\tspComp = pAggrField;\n"
	append code "\tif (!spObjAccess || !spComp) \{\n"
	append code "\t\tcout << \"Failed to create SU for $name\" << endl;\n"
	append code "\t\tpiCatalog->Release(); piCatalog = 0;\n"
	append code "\t\treturn 3;\n"
	append code "\t\}\n"
	append code "\tspObjKey = spObjAccess->GetAttrKey(\"PositionIndex\");\n"
	append code "\tif (!spObjKey) \{\n"
	append code "\t\tcout << \"Failed to create SU for $name\" << endl;\n"
	append code "\t\tpiCatalog->Release(); piCatalog = 0;\n"
	append code "\t\treturn 3;\n"
	append code "\t\}\n"
	set anal [ICC_analyze_bc_line $bc]
	# puts "anal = $anal"
	foreach restraint $anal {
	    set sname [lindex $restraint 1]
	    set title [lindex $restraint 2]
	    set def [lindex $restraint 3]
	    set phystype [lindex $restraint 4]
	    set datatype [lindex $restraint 5]
	    set isLiteral 0
	    set isvel 0
	    
	    set SU "\tnextName = \"ICCCFD${sname}\";\n"
	    if {[string toupper $sname] == "VELOCITY"} {
		set isvel 1
		append SU "\tnextSU = \"SAM3DVector\";\n"
	    } elseif {$phystype != "" && $datatype != "" \
			  && $phystype != "NONE"} {
		append SU "\tnextSU = \"SAMLiteral\";\n"
	    } else {
		set isLiteral 1
	    }
	    
	    if {!$isLiteral} {
		set var ICCCFD${sname}
		if ![info exists basicComponents($var)] {
		    set basicComponents($var) 1
		    
		    puts "SU = $SU"
		    append code $SU
		    append code "\tCATUnicodeString ${var}CompName = nextName;\n"
		    append code "\tCATSamCatalogFactory::CreateBasicComponent(\\\&nextName, \\\&nextSU, \\\&pNextField, \\\&piCatalog);\n"
		    append code "\tnextName = \"$phystype\";\n";
		    append code "\tCATSamCatalogFactory::SetPhysicalType(pNextField, \\\&nextName);\n"
		    append code "\tnextName = \"$datatype\";\n";
		    append code "\tCATSamCatalogFactory::SetDataType(pNextField, \\\&nextName);\n"
		    if {$isvel == 1} {
			append code "\tlabels\[0\] = \"Vx\";\n";
			append code "\tlabels\[1\] = \"Vy\";\n";
			append code "\tlabels\[2\] = \"Vz\";\n";
			append code "\tlabels\[3\] = \"Norm\";\n";
			append code "\tnlabels = 4;\n";
		    } else {
			append code "\tlabels\[0\] = \"$title\";\n";
			append code "\tnlabels = 1;\n";
		    }
		    append code "\tCATSamCatalogFactory::SetLabels(pNextField, nlabels, labels);\n"
		} else {
		    append code "\tnextName = \"${var}_${name}\";\n"
		    append code "\tnextSU = ${var}CompName;\n"
		    append code "\tCATSamCatalogFactory::CreateBasicComponent(\\\&nextName, NULL, \\\&pNextField, \\\&piCatalog);\n"
		}
		append code "\tspObj = pNextField;\n"
	    } else {
		append code "\tspParm = spCkeFact->CreateReal(\"$title\", \"$def\");\n"
		append code "\tif (spParm == NULL_var) \{\n"
		append code "\t\tcout << \"Failed to create SU for $name\" << endl;\n"
		append code "\t\tpiCatalog->Release(); piCatalog = 0;\n"
		append code "\t\treturn 3;\n"
		append code "\t\}\n"
		append code "\tspObj = spParm;\n"
	    }
	    append code "\tspComp->AddSubComponent(spObj);\n"
	    append code "\tspObjAccess->SetString(spObjKey, \"$col,1\");\n"
	    incr col
	}
    }
    append code "\tCATSamCatalogFactory::SetBasicComponent(\\\&nextCompName, pNextEntity, \\\&piCatalog);\n"
    append code "\tspSupport = pNextEntity;\n"
    append code "\tif (spSupport != NULL_var) \{\n"
    append code "\t\tspSupport->SetAuthorizedSupports((int) (SupportId_Surface + SupportId_MechanicalFeature));\n"
    append code "\t\tspSupport->SetMinAndMaxEntitiesNumber(1,-1);\n"
    append code "\};\n"
    append code "\tpNextEntity->Release(); pNextEntity = 0;\n"
    return $code
}

proc ICC_gateway_NLS {{solver ""}} {
    global gateway_categories gateway_bcs gateway_pars basicComponents
    
    catch {unset basicComponents}
    if {$solver != ""} {
	ICC_gateway_solverscheme $solver dummy.scm
    }
    
    set fp [open ICCGatewayCatalogNLS_template.CATNls]
    set file [read $fp]
    close $fp
    
    set fp [open ICCGatewayCatalogUI_template.CATNls]
    set fileui [read $fp]
    close $fp
    
    set allnames [array names gateway_bcs]
    foreach name $allnames {
	set nl $gateway_bcs($name)
	set codelines [ICC_emit_to_catalogNLS $name $nl]
	if {$codelines != ""} {
	    append catnls "[lindex $codelines 0]\n"
	    append catui "[lindex $codelines 1]\n"
	}
    }
    
    regsub __CATNLS__ $file $catnls result
    set fp [open ICCGateway/CNext/resources/msgcatalog/ICCGatewayCatalogNLS_new.CATNls w]
    puts $fp $result
    close $fp
    
    regsub __UINLS__ $fileui $catui result
    set fp [open ICCGateway/CNext/resources/msgcatalog/ICCGatewayCatalogUI_new.CATNls w]
    puts $fp $result
    close $fp
    
}

proc ICC_emit_to_catalogNLS {name bc} {
    global basicComponents gateway_categories
    set nl [llength $bc]
    
    if [ICC_check_for_MD $name] {
	return ""
    }
    
    # just a label if no sub fields
    
    set nextName ICCCFD${name}
    set nextRestraintName ICCCFD${name}Restraint
   
    append catnls "$nextRestraintName = \"$name\";\n"
    
    append catui "\n//*---------- BC $name --------- *//\n"
    append catui "$nextRestraintName.Window.Title=\"$name\";\n"
    append catui "$nextRestraintName.LabelSupport.Title=\"Support Surface\";\n"
    append catui "$nextRestraintName.ListSupport.LongHelp=\"Select the surface\";\n"
    append catui "$nextRestraintName.ListSupport.ShortHelp=\"Select the surface\";\n"
    if {$nl == 0} {
	append catui "$nextName.Label.Title=\"$name\";\n"
	append catui "$nextName.Help=\"Assign the named BC to the surface.\";\n"
	append catui "$nextName.LongHelp=\"Assign the named BC to the surface.\";\n"
	append catui "$nextName.ShortHelp=\"Assign the named BC to the surface.\";\n"
    } else {
	set var ICCCFD${name}
	if ![info exists basicComponents($var)] {
	    set basicComponents($var) 1
	} else {
	    error "Duplicate component entry"
	}
	set anal [ICC_analyze_bc_line $bc]
	foreach restraint $anal {
	    set sname [lindex $restraint 1]
	    set title [lindex $restraint 2]
	    set def [lindex $restraint 3]
	    set phystype [lindex $restraint 4]
	    set datatype [lindex $restraint 5]
	    set isLiteral 0
	    set isvel 0
	    
	    set nextName ICCCFD${sname}
	    if {[string toupper $sname] == "VELOCITY"} {
		set isvel 1
	    } elseif {$phystype != "" && $datatype != "" && $phystype != "NONE"} {
		# just a dummy 
	    } else {
		set isLiteral 1
	    }
	    
	    if {!$isLiteral} {
		set var ICCCFD${sname}
		if [info exists basicComponents($var)] {
		    set nextName ""
		} else {
		    set basicComponents($var) 1
		    set nextName $var
		}
		
		if {$nextName != ""} {
		    if $isvel {
			set base "${nextName}_${datatype}"
			append catui "$base.Label.Title=\"Norm\";\n"
			append catui "$base.Help=\"Change Velocity magnitude\";\n"
			append catui "$base.ShortHelp=\"Change velocity magnitude\";\n"
			append catui "$base.LongHelp=\"Change velocity magnitude\";\n"
			
			set suff(1) x
			set suff(2) y
			set suff(3) z
			for {set i 1} {$i < 4} {incr i} {
			    set sf $suff($i)
			    append catui "${base}${i}.Label.Title=\"V$sf\";\n"
			    append catui "${base}${i}.Help=\"Set $sf velocity\";\n"
			    append catui "${base}${i}.ShortHelp=\"Set $sf velocity\";\n"
			    append catui "${base}${i}.LongHelp=\"Set $sf velocity for those solvers that can handle flows hitting surface at oblique angles.\";\n"
			}
		    } else {
			append catui "$nextName.Label.Title=\"$title\";\n"
			append catui "$nextName.Help=\"Set the $title\";\n"
			append catui "$nextName.ShortHelp=\"Set the $title\";\n"
			append catui "$nextName.LongHelp=\"Set the $title\";\n"
		    }
		}
	    } else {
		# nothing to do
	    }
	}
    }
    return [list $catnls $catui]
}

proc ICC_gateway_dictionary {{solver ""}} {
    global gateway_categories gateway_bcs gateway_pars basicComponents
    
    catch {unset basicComponents}
    if {$solver != ""} {
	ICC_gateway_solverscheme $solver dummy.scm
    }
    
    set fp [open ICCGateway_template.dico]
    set file [read $fp]
    close $fp
    
    set allnames [array names gateway_bcs]
    foreach name $allnames {
	set nl $gateway_bcs($name)
	set codelines [ICC_emit_to_dictionary $name $nl]
	if {$codelines != ""} {
	    append code "${codelines}\n"
	}
    }
    regsub __FEATURES_IMPL__ $file $code result
    
    set fp [open ICCGateway/CNext/code/dictionary/ICCGateway_new.dico w]
    puts $fp $result
    close $fp
}

proc ICC_emit_to_dictionary {name bc} {
    global basicComponents gateway_categories
    
    if [ICC_check_for_MD $name] {
	return ""
    }
    
    set nextRestraintName ICCCFD${name}Restraint
    append code "$nextRestraintName\t\t\tCATISamEntityVisu\t\t\t\tlibICCGateway\n"
    append code "STRUCTURAL_${nextRestraintName}\t\t\tCATISamExplicitation\t\t\t\tlibICCGateway\n"
    return $code
}

proc ICC_gateway_bccode {{solver ""}} {
    global gateway_categories gateway_bcs gateway_pars basicComponents
    
    catch {unset basicComponents}
    if {$solver != ""} {
	ICC_gateway_solverscheme $solver dummy.scm
    }
    
    set fp [open ICCEGatewayBC_template.cpp]
    set filecode [read $fp]
    close $fp
    
    set fp [open ICCEGatewayBC_template.h]
    set fileh [read $fp]
    close $fp
    
    set fp [open ICCEGatewayBCExplicitation_template.cpp]
    set fileEcode [read $fp]
    close $fp
    
    set fp [open ICCEGatewayBCExplicitation_template.h]
    set fileEh [read $fp]
    close $fp
    
    set allnames [array names gateway_bcs]
    foreach name $allnames {
	if ![ICC_check_for_MD $name] {
	    regsub -all __BC__ $filecode $name result
	    set nfn ICCGateway/ICCGatewayBC.m/src/ICCGateway${name}.cpp
	    set fp [open $nfn w]
	    puts $fp $result
	    close $fp
	    
	    regsub -all __BC__ $fileh $name result
	    set nfn ICCGateway/ICCGatewayBC.m/LocalInterfaces/ICCGateway${name}.h
	    set fp [open $nfn w]
	    puts $fp $result
	    close $fp
	    
	    regsub -all __BC__ $fileEcode $name result
	    set nfn ICCGateway/ICCGatewayBC.m/src/ICCGateway${name}Explicitation.cpp
	    set fp [open $nfn w]
	    puts $fp $result
	    close $fp
	    
	    regsub -all __BC__ $fileEh $name result
	    set nfn ICCGateway/ICCGatewayBC.m/LocalInterfaces/ICCGateway${name}Explicitation.h
	    set fp [open $nfn w]
	    puts $fp $result
	    close $fp
	}
    }
}

proc ICC_gateway_menus {{solver ""}} {
    global gateway_categories gateway_bcs gateway_pars
    
    if {$solver != ""} {
	ICC_gateway_solverscheme $solver dummy.scm
    }
    
    set fp [open ICCGatewayCfg_template.cpp]
    set file [read $fp]
    close $fp
    
    set fp [open ICCGatewayCommandHeader_template.CATNls]
    set filehdrs [read $fp]
    close $fp
    
    set fp [open ICCGatewayCommandHeader_template.CATRsc]
    set filersc [read $fp]
    close $fp
    
    set allnames [array names gateway_categories]
    set plast pDisplaySolutionCom
    foreach name $allnames {
	set nl $gateway_categories($name)
	set codelines [ICC_emit_to_menucode $name $nl $plast]
	set cmds [lindex $codelines 0]
	if {$cmds != ""} {
	    append cmdcode "$cmds\n"
	}
	
	set menulines [lindex $codelines 1]
	if {$menulines != ""} {
	    append menucode "$menulines\n"
	}
	
	set headers [lindex $codelines 2]
	if {$menulines != ""} {
	    append cmdheaders "$headers\n"
	}
	
	set rsc [lindex $codelines 3]
	if {$menulines != ""} {
	    append cmdrsc "$rsc\n"
	}
	set plast [lindex $codelines 4]
    }
    
    regsub __BCS_CMDHEADERS__ $file $cmdcode result
    regsub __BCS_MENUS__ $result $menucode result
    set fp [open ICCGateway/ICCGatewayWB.m/src/ICCGatewayCfg_new.cpp w]
    puts $fp $result
    close $fp
    
    regsub __CMDHEADERS__ $filehdrs $cmdheaders result
    set fp [open ICCGateway/CNext/resources/msgcatalog/ICCGatewayCommandHeader_new.CATNls w]
    puts $fp $result
    close $fp
    
    regsub __CMDRSC__ $filersc $cmdrsc result
    set fp [open ICCGateway/CNext/resources/msgcatalog/ICCGatewayCommandHeader_new.CATRsc w]
    puts $fp $result
    close $fp
    
}

proc ICC_emit_to_menucode {name bcs plast} {
    if {$name == "Meshing directives"} {
	return [list "" "" "" "" $plast]
    }
    
    set isgeneric 0
    if {$name == "__nocategory__"} {
	set name "GenericBC"
	set isgeneric 1
    }
    set catname $name
    set var [ICC_name_to_var $name]
    
    set cmdhdrs "\n//*---------- Category $catname ----------*//\n"
    append cmdhdrs "ICCGatewayCommandHeader.${var}.Title = \"$catname\";\n"
    append cmdhdrs "ICCGatewayCommandHeader.${var}.Help=\"Assign $catname BCs\";\n"
    append cmdhdrs "ICCGatewayCommandHeader.${var}.ShortHelp=\"Assign $catname BCs\";\n"
    append cmdhdrs "ICCGatewayCommandHeader.${var}.LongHelp=\"Assign $catname BCs\";\n"
    
    set pbar p${var}
    set pnext $pbar
    set menus "\t\tNewAccess(CATCmdContainer,$pnext,$var);\n"
    append menus "\t\tSetAccessNext($plast, $pnext);\n"
    set plast $pnext
    
    set first 1
    set cmds ""
    foreach bc $bcs {
	set cnext ${bc}Cmd
	
	append cmdhdrs "\n//*---------------- $bc -----------------*//\n"
	append cmdhdrs "ICCGatewayCommandHeader.$cnext.Title=\"$bc\";\n"
	append cmdhdrs "ICCGatewayCommandHeader.$cnext.Help=\"Assign $bc\";\n"
	append cmdhdrs "ICCGatewayCommandHeader.$cnext.ShortHelp=\"Assign $bc\";\n"
	append cmdhdrs "ICCGatewayCommandHeader.$cnext.LongHelp=\"Assign $bc to specified surface\";\n"
	
	append cmdrsc "ICCGatewayCommandHeader.$cnext.Icon.Normal = \"I_ICCCFD$bc\";\n"
	
	append cmds "\t\tstatic CATUnicodeString ${bc}_type = \"ICCCFD${bc}Restraint\";\n"
	append cmds "\t\tnew ICCGatewayCommandHeader(\"$cnext\", \"CATAnalysisModelerUI\", \"CATSamCreateEntityCmd\", (void *) \\\&${bc}_type);\n"
	
	set pnext p$bc
	append menus "\t\tNewAccess(CATCmdStarter,$pnext,$cnext);\n"
	append menus "\t\tSetAccessCommand($pnext,\"$cnext\");\n"
	if {$first} {
	    set first 0
	    append menus "\t\tSetAccessChild($plast, $pnext);\n"
	} else {
	    append menus "\t\tSetAccessNext($plast, $pnext);\n"
	}
	set plast $pnext
    }
    return [list $cmds $menus $cmdhdrs $cmdrsc $pbar]
}

# Utilities

proc ICC_check_for_MD {name} {
    global gateway_gategories
    
    set md "Meshing directives"
    if [info exists gateway_categories($md)] {
	set meshing $gateway_categories($md)
	if {[lsearch $meshing $name] >= 0} {
	    return 1
	}
    }
    return 0
}

proc ICC_analyze_bc_line {bc} {
    
    # pass 1 -- create rep of analyzed line
    
    foreach line $bc {
	set pos [lindex $line 0]
	set name [lindex $line 1]
	set title [lindex $line 4]
	set def [lindex $line 5]
	
	set standardname $name
	if {$name == "_noname_"} {
	    if {$title != "_notitle_"} {
		if {$title == "X Velocity"} {
		    set standardname "VX"
		} elseif {$title == "Y Velocity"} {
		    set standardname "VY"
		} elseif {$title == "Z Velocity"} {
		    set standardname "VZ"
		} else {
		    set standardname $title
		}
	    }
	} elseif {$title == "_notitle_"} {
	    set title $name
	}
	lappend sline [list $pos $standardname $title $def]
    }
    
    # pass 2 -- see if we can make a velocity vector
    
    
    for {set i 0} {$i < [llength $sline]} {incr i} {
	set line [lindex $sline $i]
	set curname [lindex $line 1]
	set title [lindex $line 2]
	
	set done 0
	if {$curname == "VX"} {
	    set yname [lindex [lindex $sline [expr $i+1]] 1]
	    set zname [lindex [lindex $sline [expr $i+2]] 1]
	    if {$yname == "VY" && $zname == "VZ"} {
		lappend result [list $i "Velocity" "Velocity" {0. 0. 0.} TRANSLATIONAL_VELOCITY SPEED]
		set i [expr $i + 2]
		set done 1
	    }
	} elseif {$curname == "Temperature"} {
	    lappend result [list $i $curname $title 0. TEMPERATURE TEMPERATURE]
	    set done 1
	} elseif {$curname == "Thermal Conductivity"} {
	    lappend result [list $i "Thermal_Conductivity" $title 0. THERMALCONDUCTIVITY THERMALCONDUCTIVITY]
	    set done 1
	} elseif {$curname == "Pressure"} {
	    lappend result [list $i $curname $title 0. PRESSURE PRESSURE]
	    set done 1
	}
	
	if {!$done} {
	    lreplace line 0 0 $i
	    lappend line NONE
	    lappend result $line
	}
    }
    return $result
}

proc ICC_name_to_var {name} {
    regsub -all {[\t\ \n]} $name "" result
    return $result
}
