#
# Copyright © 2020 MSC.Software Corporation
#  
# Permission to use Scripts
#  
# Permission is granted to MSC.Software customers with valid licenses of the MSC Apex™ software 
# to use script files posted on this page (collectively “Scripts”) solely for customers’ own authorized 
# internal use in conjunction with licensed use of the MSC Apex software.  
# No other use is permitted.  No license to MSC Apex or other software is granted under this Permission.
#  
# SCRIPTS ARE PROVIDED ON AN "AS-IS" BASIS, WITH NO WARRANTIES OF ANY KIND.  USE OF THE SCRIPTS IS AT CUSTOMER'S SOLE RISK.
#  
# IN NO EVENT SHALL MSC.SOFTWARE CORPORATION, ITS AFFILIATES, SUBSIDIARIES, SUPPLIERS, AGENTS, REPRESENTATIVES OR EMPLOYEES BE LIABLE FOR ANY 
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, TORT, 
# STRICT LIABILITY, OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION USE OF THE SCRIPTS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
#  
# Customer shall indemnify, defend and hold MSC.Software Corporation, its affiliates, subsidiaries, suppliers, agents, 
# employees or representatives (collectively, “Indemnified Parties”) harmless from and against any third-party claims 
# brought against Indemnified Parties rising out of or in connection with Customer’s use of the Scripts.
#
import sys
import os
import apex_sdk
import clr

#.NET references
import System
import System.Windows.Controls as WPFControls
from System.Windows.Automation import AutomationProperties
from Microsoft.Win32 import OpenFileDialog



#setting pre-defined properties of tool_propertyContainer
def getUIContent():
	my_toolProperty = apex_sdk.ToolPropertyContainer()
	
	my_toolProperty.TitleText = "Create 3D Bolts"
	
	file_path = os.path.dirname(os.path.realpath(__file__))
	my_toolProperty.TitleImageUriString = os.path.dirname(file_path)  + '\\res\\create_3D_bolts.png'
	
	
	my_toolProperty.WorkFlowInstructions = """<HTML><BODY><P STYLE=\"font-size:10;\"><SPAN>Identifies CAD Bolts and creates 1d connectors.</SPAN></P>
	<P><SPAN> </SPAN></P>
	<P STYLE=\"font-size:10;\"><SPAN>The tool will use curves with custom attributes that origins from the Identify bolts tool. ALl unmeshed parts are put in hide, so all parts connected need to be meshed.
	Idealized Hex-meshed models representing bolts, nut and washer are created. 
	Contacts (glued and touching) will be created. If the  model is exported as bdf using the apex_utils script trigger, and, there filename prefix is "sol400" a 
	run ready Nastran sol400 job is exported with prestressed bolts.
	Preloads are either taken from a lookup text file, or, can be overridden by preload indicated using tag incuded in the name of the curve object. Ie Curve 1 # 12000N or Curve 10 
	Refer to the Apex Utils documentation for more info. If model is run in integretade solver all contact are glued and no preload step is created</SPAN></P>
	<P><SPAN> </SPAN></P>
	<P STYLE=\"font-size:10;\"><SPAN>Send questions, comments to stefan.tynelius@hexagon.com Elvis sightings are also continuoulsy managed by larry.pearce@hexagon.com</SPAN></P></BODY></HTML>"""

	
	
	#handle apply button (green) click event
	my_toolProperty.AppliedCommand = apex_sdk.ActionCommand(System.Action(HandleApplyButton))
	# handle exit button (red) click event
	my_toolProperty.ExitCommand = apex_sdk.ActionCommand(System.Action(HandleExitButton))
	
	my_toolProperty.ToolPropertyContent = getCustomToolPropertyContent()
	
	#define pickFiterTools
	my_toolProperty.ShowPickChoice = True
	my_toolProperty.IsCustomTool = True
	#setPickFilterTools()
	my_toolProperty.PickFilterList = setPickFilterTools()
	
	return my_toolProperty





def getCustomToolPropertyContent():

	my_Grid = WPFControls.Grid()

	createLayout(my_Grid, 12, 2)
	
	iRow = 1
	
	#global nameTextBox
	#nameTextBox = createDataBox(my_Grid, "Name: ", "", iRow, 0)
	#iRow += 1
	
	global fastenerTypeComboBox, fastenerTypeTextBlock
	fastenerTypeTextBlock = createTextBlock(my_Grid, "Bolt Type:", iRow, 0)
	fastenerTypeComboBox  = createComboBox(my_Grid, iRow, 1)
	updateComboBox(fastenerTypeComboBox, ["SOL 400 (split bolts)", "Mentat (no split)"])
	iRow += 1
	
	fastenerTypeComboBox.SelectionChanged += fastenerTypeComboBoxCB
	
	fastenerTypeComboBox.Visibility       = System.Windows.Visibility.Collapsed
	fastenerTypeTextBlock.Visibility         = System.Windows.Visibility.Collapsed
	
	iRow += 1
	
	global splitLocationComboBox, splitLocationTextBlock
	splitLocationTextBlock = createTextBlock(my_Grid, "Bolt Type:", iRow, 0)
	splitLocationComboBox  = createComboBox(my_Grid, iRow, 1)
	updateComboBox(splitLocationComboBox, ["Split between head and nut", "Split right under Head", "Split above Nut", "Split at Percentage from Head","Split at Distance from Head"])
	iRow += 1
	
	global splitPercentageTextBox, splitPercentageTextBlock
	splitPercentageTextBlock = createTextBlock(my_Grid, "Split Percentage from Head: ", iRow, 0)
	splitPercentageTextBox   = createTextBox(my_Grid, "20", iRow, 1)
	iRow += 1
	
	splitPercentageTextBlock.Visibility       = System.Windows.Visibility.Collapsed
	splitPercentageTextBox.Visibility         = System.Windows.Visibility.Collapsed
	
	global splitDistanceTextBox, splitDistanceTextBlock
	splitDistanceTextBlock = createTextBlock(my_Grid, "Split Distance from Head:", iRow, 0)
	splitDistanceTextBox   = createTextBox(my_Grid, "25", iRow, 1)
	
	splitDistanceTextBlock.Visibility       = System.Windows.Visibility.Collapsed
	splitDistanceTextBox.Visibility         = System.Windows.Visibility.Collapsed
	
	iRow += 1
	
	splitLocationComboBox.SelectionChanged += splitLocationComboBoxCB
	

	global meshsizeTextBox, meshsizeTextBlock
	meshsizeTextBlock = createTextBlock(my_Grid, "Bolt Mesh Size:", iRow, 0)
	meshsizeTextBox   = createTextBox(my_Grid, "5", iRow, 1)
	iRow += 1
	
	global matlComboBox, matlComboTextBlock
	matlComboTextBlock = createTextBlock(my_Grid, "Material:", iRow, 0)
	matlComboBox       = createComboBox(my_Grid, iRow, 1)
	iRow += 1
	
	global boltTipGlueToleranceTextBox, boltTipGlueToleranceTextBlock
	boltTipGlueToleranceTextBlock = createTextBlock(my_Grid, "Bolt Tip Glue Tolerance:", iRow, 0)
	boltTipGlueToleranceTextBox   = createTextBox(my_Grid, "0.5", iRow, 1)
	iRow += 1
	
	global boltTopTouchToleranceTextBox,boltTopTouchToleranceTextBlock
	boltTopTouchToleranceTextBlock = createTextBlock(my_Grid, "Bolt Top Touch Tolerance:", iRow, 0)
	boltTopTouchToleranceTextBox   = createTextBox(my_Grid, "0.1", iRow, 1)
	iRow += 1
	
	global boltFrictionTextBox,boltFrictionTextBlock
	boltFrictionTextBlock = createTextBlock(my_Grid, "Bolt Friction:", iRow, 0)
	boltFrictionTextBox   = createTextBox(my_Grid, "0.15", iRow, 1)
	iRow += 1
	

	file_path = os.path.dirname(os.path.realpath(__file__))
	script_path= os.path.join(file_path, 'auGetMaterials.py')
	apex_sdk.runScriptFunction(script_path, "main", callback=getMatls)
	
	# global stiffnessComboTextBlock, stiffnessComboBox
	# stiffnessComboTextBlock = createTextBlock(my_Grid, "Stiffness:", iRow, 0)
	# stiffnessComboBox  = createComboBox(my_Grid, iRow, 1)
	# updateComboBox(stiffnessComboBox, ["Nastran QRG"])
	# iRow += 1
	
	#global toleranceTextBox, toleranceTextBlock
	#toleranceTextBlock = createTextBlock(my_Grid, "Tolerance:", iRow, 0)
	#toleranceTextBox   = createTextBox(my_Grid, "0.3", iRow, 1)
	#iRow += 1
	
	# global distributionTypeComboBox, distributionTypeTextBlock
	# distributionTypeTextBlock = createTextBlock(my_Grid, "Distribution Type:", iRow, 0)
	# distributionTypeComboBox  = createComboBox(my_Grid, iRow, 1)
	# updateComboBox(distributionTypeComboBox, ["Compliant - RBE3 ", "Rigid - RBE2"])
	# iRow += 1
	
	
	
	
	return my_Grid




def fastenerTypeComboBoxCB(sender, event):
	# I need to learn and understand sender and event
	global fastenerTypeComboBox
	global meshsizeTextBlock, meshsizeTextBox
	global matlComboTextBlock, matlComboBox
	global stiffnessComboTextBlock, stiffnessCombBox
	
	choices = fastenerTypeComboBox.SelectedValue.ToString().split(":")
	choice = choices[len(choices)-1].lstrip().rstrip()
	
	if 1 == 0:
		meshsizeTextBlock.Visibility       = System.Windows.Visibility.Visible
		meshsizeTextBox.Visibility         = System.Windows.Visibility.Visible
		matlComboTextBlock.Visibility = System.Windows.Visibility.Visible
		matlComboBox.Visibility       = System.Windows.Visibility.Visible
		#stiffnessComboTextBlock.Visibility = System.Windows.Visibility.Collapsed
		#stiffnessComboBox.Visibility       = System.Windows.Visibility.Collapsed


def splitLocationComboBoxCB(sender, event):
	# I need to learn and understand sender and event
	global splitLocationComboBox
	global splitPercentageTextBlock, splitPercentageTextBox
	global splitDistanceTextBlock, splitDistanceTextBox
	#global fastenerTypeComboBox
	global meshsizeTextBlock, meshsizeTextBox
	global matlComboTextBlock, matlComboBox
	global stiffnessComboTextBlock, stiffnessCombBox
	
	choices = splitLocationComboBox.SelectedValue.ToString().split(":")
	choice = choices[len(choices)-1].lstrip().rstrip()
	# ["Split between head and nut", "Split right under Head", "Split above Nut", "Split at Percentage from Head","Split at Distance from Head"
	if choice == "Split between head and nut" or choice == "Split right under Head" or  choice == "Split above Nut":
		splitPercentageTextBlock.Visibility       = System.Windows.Visibility.Collapsed
		splitPercentageTextBox.Visibility         = System.Windows.Visibility.Collapsed
		
		splitDistanceTextBlock.Visibility       = System.Windows.Visibility.Collapsed
		splitDistanceTextBox.Visibility         = System.Windows.Visibility.Collapsed		
	elif choice == "Split at Percentage from Head":
		splitPercentageTextBlock.Visibility       = System.Windows.Visibility.Visible
		splitPercentageTextBox.Visibility         = System.Windows.Visibility.Visible
		
		splitDistanceTextBlock.Visibility       = System.Windows.Visibility.Collapsed
		splitDistanceTextBox.Visibility         = System.Windows.Visibility.Collapsed
		
	elif choice == "Split at Distance from Head":
		splitPercentageTextBlock.Visibility       = System.Windows.Visibility.Collapsed
		splitPercentageTextBox.Visibility         = System.Windows.Visibility.Collapsed
		
		splitDistanceTextBlock.Visibility       = System.Windows.Visibility.Visible
		splitDistanceTextBox.Visibility         = System.Windows.Visibility.Visible	
	else:
		pass






def createLayout(parent, numRows, numCols):
	for k in range(numRows):
		parent.RowDefinitions.Add(WPFControls.RowDefinition())
	for k in range(numCols):
		parent.ColumnDefinitions.Add(WPFControls.ColumnDefinition())





def createComboBox(parent, row, col):
	comboBox = WPFControls.ComboBox()
	
	comboBox.Margin = System.Windows.Thickness(5.)
	
	WPFControls.Grid.SetRow(comboBox, row)
	WPFControls.Grid.SetColumn(comboBox, col)
	
	parent.Children.Add(comboBox)
	
	return comboBox



def updateComboBox(comboBox, comboItems):
	
	for comboItem in comboItems:
		item = WPFControls.ComboBoxItem()
		item.Content=comboItem
		comboBox.Items.Add(item)
	
	comboBox.SelectedIndex="0"



def createTextBlock(parent, text, row, col):
	textBlock = WPFControls.TextBlock()
	textBlock.Text = text
	
	textBlock.Margin = System.Windows.Thickness(5.)
	
	WPFControls.Grid.SetRow(textBlock, row)
	WPFControls.Grid.SetColumn(textBlock, col)
	parent.Children.Add(textBlock)
	
	return textBlock



def createTextBox(parent, value, row, col):
	textBox =WPFControls.TextBox()
	
	textBox.Margin = System.Windows.Thickness(5.)
	
	WPFControls.Grid.SetRow(textBox, row)
	WPFControls.Grid.SetColumn(textBox, col)
	textBox.Text=value
	
	parent.Children.Add(textBox)
	
	return textBox



def createDataBox(parent, title, value, row, col):
	textBlock = WPFControls.TextBlock()
	textBlock.Text = title
	WPFControls.Grid.SetRow(textBlock, row)
	WPFControls.Grid.SetColumn(textBlock, col)

	textBox =WPFControls.TextBox()
	WPFControls.Grid.SetRow(textBox, row)
	WPFControls.Grid.SetColumn(textBox, col+1)
	textBox.Text=value
	
	parent.Children.Add(textBlock)
	parent.Children.Add(textBox)
	
	return textBox






#set pickFilers
#some pick choices are commented out
def setPickFilterTools():
	pickChoices = System.Collections.Generic.List[System.String]()
	
	#exclusive picking and visibility picking	
	pickChoices.Add(apex_sdk.PickFilterTypes.ExclusivePicking)
	pickChoices.Add(apex_sdk.PickFilterTypes.VisibilityPicking)
	
	#Assembly and part
	#pickChoices.Add(apex_sdk.PickFilterTypes.Assembly)
	#pickChoices.Add(apex_sdk.PickFilterTypes.Part)
	
	#Bodies	
	#pickChoices.Add(apex_sdk.PickFilterTypes.SolidMesh)
	#pickChoices.Add(apex_sdk.PickFilterTypes.Solid)
	#pickChoices.Add(apex_sdk.PickFilterTypes.SurfaceMesh)
	#pickChoices.Add(apex_sdk.PickFilterTypes.Surface)
	#pickChoices.Add(apex_sdk.PickFilterTypes.CurveMesh)
	pickChoices.Add(apex_sdk.PickFilterTypes.Curve)
	#pickChoices.Add(apex_sdk.PickFilterTypes.Point)
	
	#features
	#pickChoices.Add(apex_sdk.PickFilterTypes.CellMesh)
	#pickChoices.Add(apex_sdk.PickFilterTypes.FaceMesh)
	#pickChoices.Add(apex_sdk.PickFilterTypes.EdgeMesh)
	#pickChoices.Add(apex_sdk.PickFilterTypes.Cell)
	#pickChoices.Add(apex_sdk.PickFilterTypes.VertexMesh)
	
	#Lower Dimensional Entities
	#pickChoices.Add(apex_sdk.PickFilterTypes.Element3D)
	#pickChoices.Add(apex_sdk.PickFilterTypes.Element2D)
	#pickChoices.Add(apex_sdk.PickFilterTypes.Face)
	#pickChoices.Add(apex_sdk.PickFilterTypes.MeshSeed)
	#pickChoices.Add(apex_sdk.PickFilterTypes.Element1D)
	#pickChoices.Add(apex_sdk.PickFilterTypes.Edge)
	#pickChoices.Add(apex_sdk.PickFilterTypes.SeedPoint)
	#pickChoices.Add(apex_sdk.PickFilterTypes.Node)
	#pickChoices.Add(apex_sdk.PickFilterTypes.Vertex)
	
	#Sub Lower Dimensional Entities
	#pickChoices.Add(apex_sdk.PickFilterTypes.ElementEdge)
	#pickChoices.Add(apex_sdk.PickFilterTypes.ElementFace)
	
	#Interactions and connections
	#pickChoices.Add(apex_sdk.PickFilterTypes.DiscreteTie)
	#pickChoices.Add(apex_sdk.PickFilterTypes.Connector)
	#pickChoices.Add(apex_sdk.PickFilterTypes.EdgeTie)
	#pickChoices.Add(apex_sdk.PickFilterTypes.Joint)
	#pickChoices.Add(apex_sdk.PickFilterTypes.Glue)
	
	#LBCs
	#pickChoices.Add(apex_sdk.PickFilterTypes.Pressure)
	#pickChoices.Add(apex_sdk.PickFilterTypes.Gravity)
	#pickChoices.Add(apex_sdk.PickFilterTypes.Constraint)
	#pickChoices.Add(apex_sdk.PickFilterTypes.ForceMoment)
	#pickChoices.Add(apex_sdk.PickFilterTypes.EnforcedMotion)
	
	#Attributes and other objects
	#pickChoices.Add(apex_sdk.PickFilterTypes.CompositeZone)
	#pickChoices.Add(apex_sdk.PickFilterTypes.LayeredPanel)
	#pickChoices.Add(apex_sdk.PickFilterTypes.InterfacePoint)
	#pickChoices.Add(apex_sdk.PickFilterTypes.PointMass)
	#pickChoices.Add(apex_sdk.PickFilterTypes.BeamSpan)
	#pickChoices.Add(apex_sdk.PickFilterTypes.Offset)
	
	#Sensors
	#pickChoices.Add(apex_sdk.PickFilterTypes.MotionEnvelopeSensor)
	#pickChoices.Add(apex_sdk.PickFilterTypes.ClearanceSensor)
	#pickChoices.Add(apex_sdk.PickFilterTypes.CrossSectionSensor)
	#pickChoices.Add(apex_sdk.PickFilterTypes.PointSensor)
	
	#Coordinate system
	#pickChoices.Add(apex_sdk.PickFilterTypes.CoordinateSystem)
	
	#Tool Registration
	#Tool Name has to be the same
	#apex_sdk.PickFilterRegistration.RegisterTool("Auto Tie Nodes", pickChoices)
	return pickChoices






@apex_sdk.errorhandler
def HandleApplyButton():
	# Create a Dictionary to store the user defined tool data  
	dictionary = {}
	
	choices = fastenerTypeComboBox.SelectedValue.ToString().split(":")
	choice = choices[len(choices)-1].lstrip().rstrip()
	dictionary["fastenerType"] = choice
	
	choices = matlComboBox.SelectedValue.ToString().split(":")
	choice = choices[len(choices)-1].lstrip().rstrip()
	dictionary["material"] = choice
	
	#dictionary["distributionType"] = distributionTypeComboBox.Text
	dictionary["meshsize"]  = meshsizeTextBox.Text
	#dictionary["name"]      = nameTextBox.Text
	
	choices = splitLocationComboBox.SelectedValue.ToString().split(":")
	choice = choices[len(choices)-1].lstrip().rstrip()
	dictionary["splitLocation"] = choice
	
	dictionary["splitPercentage"]= splitPercentageTextBox.Text
	
	dictionary["splitDistance"]= splitDistanceTextBox.Text
	
	dictionary["boltTipGlueTolerance"]=boltTipGlueToleranceTextBox.Text
	dictionary["boltTopTouchTolerance"]=boltTopTouchToleranceTextBox.Text	
	dictionary["boltFriction"]=boltFrictionTextBox.Text	

	
	
	
	
	file_path = os.path.dirname(os.path.realpath(__file__))
	script_path= os.path.join(file_path, 'Create3dBolts_v03a.py')
	
	apex_sdk.runScriptFunction(script_path, "main", dictionary)
	
	
	
	
	
	
# exit button (red) from tool header
@apex_sdk.errorhandler
def HandleExitButton():
	print("HandleExitButton")
	file_path = os.path.dirname(os.path.realpath(__file__))
	script_path= os.path.join(file_path, 'Create3dBolts_v03a.py')
	# Create a Dictionary to store the user defined tool data  
	dictionary = {}
	
	#choices = frameTypeComboBox.SelectedValue.ToString().split(":")
	#choice = choices[len(choices)-1].lstrip().rstrip()
	
	apex_sdk.runScriptFunction(script_path, "exectuteOnExit", dictionary)





#This function receives data from the Script API function and updates the Tool UI 
@apex_sdk.errorhandler
def getMatls():
	global matlComboBox
	
	ret_dict = apex_sdk.getScriptFunctionReturnData()
	
	matls = ret_dict["matlList"]
	
	updateComboBox(matlComboBox, matls)

