#
# 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.
#
#
# 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
import csv

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


global utils_path
file_path = os.path.dirname(os.path.realpath(__file__))
utils_path= os.path.dirname(os.path.realpath(file_path)) + "\\res"
xml_file= os.path.join(utils_path, 'UtilityUserSettings.xml')


def read_settings(settings_file, tmp_h=""):
	silent_flag = True
	#
	# settings_file=r'C:\Users\e7390\Documents\Predator\Topics\Scripting\Sample_files\UtilityUserSettings.xml'
	inf = open(settings_file, 'r')
	lines = inf.readlines()
	inf.close()
	keys = []
	SettingsD = {}
	n = 0
	while n < len(lines):
		if lines[n].find('<') > -1 and  lines[n].find('\\') < 0 and lines[n].find('/') < 0:
			# found start tag
			# print lines[n]
			tmp = lines[n].strip().replace('<', '').replace('>', '')
			# print tmp
			endtag = "<\\" + tmp + ">"
			endtag2 = "</" + tmp + ">"
			# print endtag
			n += 1
			SettingsD[tmp] = {}
			while lines[n].find(endtag) < 0 and lines[n].find(endtag2) <0 :
				#while lines[n].find(endtag) < 0 :
				if lines[n].find('=') > 1:
					newkey = lines[n].strip().split('=')[0]
					SettingsD[tmp][newkey] = lines[n].strip().split('=')[1]
					n += 1
				elif lines[n].find('#') == 0:
					continue
				else:
					# not a valid settnigs command
					#print "Not a valid settngs command: " + lines[n]
					n += 1
				#print(lines[n])
		n += 1

	# supress write out of all settings

	if silent_flag != True:
		if tmp_h != -1:
			print("====")
			print("Following setting groups detected:")

		for item in reversed(sorted(SettingsD.keys())):
			if tmp_h != -1:
				print("==== " + item + "   " + " ====")

			for key in list(SettingsD[item].keys()):
				if tmp_h != "" and tmp_h != -1:
					print("%-16s : %-12s" % (key, SettingsD[item][key].strip()))
				elif tmp_h == -1:
					continue
				else:
					print("%-16s : %-12s" % (key, SettingsD[item][key].strip()))
	#
	return SettingsD

def getUIContent():

	my_toolProperty = apex_sdk.ToolPropertyContainer()
	my_toolProperty.ToolPropertyContent = getCustomToolPropertyContent()

	my_toolProperty.TitleText = "Export Random bdf"

	file_path = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
	my_toolProperty.TitleImageUriString = file_path + "\\res\\icon_111.png"

	my_toolProperty.WorkFlowInstructions = """<HTML><BODY><P STYLE=\"font-size:10;\"><SPAN>Export bdf for Random Response</SPAN></P>
	<P><SPAN> </SPAN></P>
	<HTML><BODY><P STYLE=\"font-size:10;\"><SPAN>Please read the documentation to properly use the utility.</SPAN></P>
	<P><SPAN> </SPAN></P>
	<P STYLE=\"font-size:10;\"><SPAN>Send questions to javier.lazaroortega@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))

	#define pickFiterTools
	#my_toolProperty.ShowPickChoice = True
	#my_toolProperty.IsCustomTool = True
	#my_toolProperty.PickFilterList = setPickFilterTools()



	return my_toolProperty

def createTextBlock(parent, text, iRow, iCol):
	textBlock = WPFControls.TextBlock()
	textBlock.Text = text

	textBlock.Margin = System.Windows.Thickness(5.)

	WPFControls.Grid.SetRow(textBlock, iRow)
	WPFControls.Grid.SetColumn(textBlock, iCol)
	parent.Children.Add(textBlock)

	return textBlock

def updateComboBox(comboBox, comboItems):

	for comboItem in comboItems:
		item = WPFControls.ComboBoxItem()
		item.Content=comboItem
		comboBox.Items.Add(item)

def createEmptyRow(parent, iRow):
	textBlock = WPFControls.TextBlock()
	textBlock.Text = ""
	WPFControls.Grid.SetRow(textBlock, iRow)
	WPFControls.Grid.SetColumn(textBlock, 0)

	parent.Children.Add(textBlock)

	return

def getCustomToolPropertyContent():
	global dictionary
	global utils_path
	global my_Grid

	# # get defaults from settings file
	file_path = os.path.dirname(os.path.realpath(__file__))
	#utils_path= os.path.dirname(os.path.realpath(file_path))
	settings_file= os.path.join(utils_path, 'UtilityUserSettings.xml')

	global SettingsD
	SettingsD=read_settings(settings_file)

	my_Grid = WPFControls.Grid()

	createLayout(my_Grid, 2, 1)

	iRow = 0
	iCol = 0

	# get defaults from settings file
	file_path = os.path.dirname(os.path.realpath(__file__))
	#utils_path= os.path.dirname(os.path.realpath(file_path))
	settings_file= os.path.join(utils_path, 'UtilityUserSettings.xml')
	SettingsD=read_settings(settings_file)

	######################
	my_SubGrid1 = WPFControls.Grid()
	createLayout(my_SubGrid1, 5, 2)
	###########
	global RunNastranCheckBox
	RunNastranCheckBox = createCheckBox(my_SubGrid1, "Run Nastran", True, 0, 0)
	###########

	# ---- Scenarios----

	global scenariosComboBox, scenariosComboTextBlock
	scenariosComboTextBlock = createTextBlock(my_SubGrid1, "Scenario:", 1, 0)
	scenariosComboBox       = createComboBox2(my_SubGrid1, 1, 1)
	###########

	scenariosComboTextBlock.Visibility = System.Windows.Visibility.Visible
	scenariosComboBox.Visibility       = System.Windows.Visibility.Visible

	global user_table
	user_table = Table_import(my_SubGrid1, "Table import", 2, 0)

	global nastranPath
	nastranPath = BDFBrowser(my_SubGrid1, "BDF Path", 3, 0)

	global TableTitleTextBlock
	TableTitleTextBlock = createTextBlock(my_SubGrid1, "PSD table:", 4, 0)

	WPFControls.Grid.SetRow(my_SubGrid1, iRow)
	WPFControls.Grid.SetColumn(my_SubGrid1, 0)
	my_Grid.Children.Add(my_SubGrid1)
	######################
	iRow += 1
	# Get both scenarios and events
	file_path = os.path.dirname(os.path.realpath(__file__))
	script_path_parts= os.path.join(file_path, 'getScenariosAndEvents.py')
	apex_sdk.runScriptFunction(script_path_parts, "main", callback=getNewScenariosCB)

	global table_row
	table_row = iRow
	create_table('')



	#Return the Grid
	return my_Grid

def scenariosComboBoxCB(sender, event):
	global scenariosComboBox
	global eventComboBox
	global eventNameL
	global scenarioNameL

	choices = scenariosComboBox.SelectedValue.ToString().split(":")
	_scenario_name = choices[len(choices)-1].lstrip().rstrip()
	# # # get list of scenarios and events
	#try:
	if 1==1:
		ret_dict = apex_sdk.getScriptFunctionReturnData()
		scenarios = ret_dict["ScenarioList"]
		eventL = ret_dict["EventL"]

	my_eventNameL=[]
	n=0
	while n < len(scenarios):

		if scenarios[n] == _scenario_name:
			my_eventNameL=eventL[n].split('¤')
		n+=1

	scenarioNameL=scenarios
	eventNameL=eventL

	refreshComboBox(eventComboBox, my_eventNameL)

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 createComboBox2(parent, iRow, iCol):
	comboBox = WPFControls.ComboBox()

	comboBox.Margin = System.Windows.Thickness(5.)

	WPFControls.Grid.SetRow(comboBox, iRow)
	WPFControls.Grid.SetColumn(comboBox, iCol)

	parent.Children.Add(comboBox)

	return comboBox

def refreshComboBox(comboBox, comboItems):
	comboBox.Items.Clear()
	for comboItem in comboItems:
		item = WPFControls.ComboBoxItem()
		item.Content=comboItem
		comboBox.Items.Add(item)

	comboBox.SelectedIndex="0"

def updateComboBox2(comboBox, comboItems):
	n=0
	for comboItem in comboItems:
		item = WPFControls.ComboBoxItem()
		item.Content=comboItem
		comboBox.Items.Add(item)
		n+=1
	try:
		comboBox.SelectedIndex="0"
	except:
		pass
		print("could not set combobox index")

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

	textBox =WPFControls.TextBox()
	WPFControls.Grid.SetRow(textBox, iRow)
	WPFControls.Grid.SetColumn(textBox, iCol+1)
	textBox.Text=value

	parent.Children.Add(textBlock)
	parent.Children.Add(textBox)

	return textBox

def createDataBox2(parent, value, iRow, iCol):
	textBox =WPFControls.TextBox()
	WPFControls.Grid.SetRow(textBox, iRow)
	WPFControls.Grid.SetColumn(textBox, iCol)
	textBox.Text=value

	parent.Children.Add(textBox)

	return textBox

def createCheckBox(parent, title, active, iRow, iCol):
	myWrapPanel = WPFControls.WrapPanel()
	myWrapPanel.Orientation = WPFControls.Orientation.Vertical

	CheckBox = WPFControls.CheckBox()
	CheckBox.Content = title
	myWrapPanel.Children.Add(CheckBox)

	WPFControls.Grid.SetRow(myWrapPanel, iRow)
	WPFControls.Grid.SetColumn(myWrapPanel, iCol)
	CheckBox.IsChecked = System.Nullable[System.Boolean](active)

	parent.Children.Add(myWrapPanel)

	return CheckBox

def create_table(path):
	dataGrids = {}
	dataGrids= WPFControls.DataGrid()
	WPFControls.Grid.SetRow(dataGrids, table_row)
	WPFControls.Grid.SetColumn(dataGrids, 0)
	dataGrids.Height = 150
	dataGrids.Height = 300

	global data_table
	data_table = WPFData.DataTable("Part Contents")
	if path == '':
		data_table.Columns.Add("Frecuency")
		data_table.Columns.Add("Magnitude")
		data_table.Rows.Add(str(SettingsD['NASTRAN_JOB_SETUP']['RANDOMPSD_Frec']),str(SettingsD['NASTRAN_JOB_SETUP']['RANDOMPSD_Mag']))

	else:
		try:
			data_table.Columns.Add("Frecuency")
			data_table.Columns.Add("Magnitude")

			with open(path, mode='r') as csv_file:
				csv_reader = csv.DictReader(csv_file)
				line_count = 0
				for row in csv_reader:
					if line_count == 0:
						line_count += 1
					data_table.Rows.Add(row['Frecuency'],row['Magnitude'])
					line_count += 1

		except:
			print("Failed on import .csv")
	# dataGrids[sheet_name].HorizonatAlignment = "Streched"
	dataGrids.ItemsSource = data_table.DefaultView

	# Add the DataGrid to the Grid
	my_Grid.Children.Add(dataGrids)

#Function to handle the Import Button "Click" event
#This function gets called every time the Button is clicked
@apex_sdk.errorhandler
def HandleSaveBtn(sender,args):

	#Create a File open dialog
	#dialog = OpenFileDialog()
	dialog = SaveFileDialog()

	#Configure for single file selection
	dialog.Multiselect = False

	#Set up the file types you want to support
	dialog.Filter = "All Files  |*.*"
	#dialog.Filter = "MWF Files  |*.mwf* | All Files  |*.*"

	#Display the dialog
	#If it returns anything
	#   get the file name
	#   display it on the text nox
	if dialog.ShowDialog():
		selectedFile = dialog.FileName
		fileTextBox.Text = selectedFile

@apex_sdk.errorhandler
def BDFBrowser(parent, title, row, col):
	textBox =WPFControls.TextBox()
	textBox.Margin = System.Windows.Thickness(5.)
	textBox.Width = 150
	WPFControls.Grid.SetRow(textBox, row)
	WPFControls.Grid.SetColumn(textBox, col)

	def button(sender,args):
		dialog = SaveFileDialog()
		#Configure for single file selection
		dialog.Multiselect = False
		# #Set up the file types you want to support
		dialog.Filter = " (*.bdf) | *.bdf"
		dialog.DefaultExt = "*.bdf"
		if dialog.ShowDialog():
			textBox.Text = dialog.FileName

	BtnSave = WPFControls.Button()
	BtnSave.Content = title
	WPFControls.Grid.SetRow(BtnSave, row)
	WPFControls.Grid.SetColumn(BtnSave,col+1)
	BtnSave.Click += button


	parent.Children.Add(textBox)
	parent.Children.Add(BtnSave)
	return textBox

@apex_sdk.errorhandler
def Table_import(parent, title, row, col):
	textBox =WPFControls.TextBox()
	textBox.Margin = System.Windows.Thickness(5.)
	textBox.Width = 150
	WPFControls.Grid.SetRow(textBox, row)
	WPFControls.Grid.SetColumn(textBox, col)

	def button(sender,args):
		dialog = OpenFileDialog()
		#Configure for single file selection
		dialog.Multiselect = False
		# #Set up the file types you want to support
		dialog.Filter = "  (*.csv) | *.csv"
		dialog.DefaultExt = "*.csv"
		if dialog.ShowDialog():
			textBox.Text = dialog.FileName
			create_table(dialog.FileName)

	BtnSave = WPFControls.Button()
	BtnSave.Content = title
	WPFControls.Grid.SetRow(BtnSave, row)
	WPFControls.Grid.SetColumn(BtnSave,col+1)
	BtnSave.Click += button

	parent.Children.Add(textBox)
	parent.Children.Add(BtnSave)
	return textBox

@apex_sdk.errorhandler
def HandleApplyButton():
	file_path = os.path.dirname(os.path.realpath(__file__))
	script_path= os.path.join(file_path, 'bdfExport_RANDOM.py')
	# Create a Dictionary to store the user defined tool data
	dictionary = {}
	dictionary["xml_file"] = xml_file
	dictionary["bdf_path"] = nastranPath.Text
	dictionary["Scenario"] = scenariosComboBox.Text
	dictionary["RunNastran"] = RunNastranCheckBox.IsChecked
	dictionary["Frecuency"] = []
	dictionary["Magnitude"] = []
	for datarow in data_table.Rows:
		dictionary["Frecuency"].append(float(datarow["Frecuency"]))
		dictionary["Magnitude"].append(float(datarow["Magnitude"]))

	# choices = exportOptionComboBox.SelectedValue.ToString().split(":")
	# choice = choices[len(choices)-1].lstrip().rstrip()
	# dictionary["RunNastran"] = choice

	apex_sdk.runScriptFunction(script_path, "main", dictionary)

# exit button (red) from tool header
@apex_sdk.errorhandler
def HandleExitButton():
	print("HandleExitButton")



#This function receives data from the Script API function and updates the Tool UI
@apex_sdk.errorhandler
def getNewScenariosCB():
	global scenariosComboBox
	global eventNameL
	global scenarioNameL
	global eventComboBox

	ret_dict = apex_sdk.getScriptFunctionReturnData()
	scenarios=[] #not using default load case


	# Build Scenario list
	try:
		tmp = ret_dict["ScenarioList"]
	except:
		print("No scenarios found")
		tmp=[]

	for item in tmp:
		scenarios.append(item)

	updateComboBox2(scenariosComboBox, reversed(scenarios) )


	scenarioNameL=scenarios
	# Get the events Dict

	# Build Event list
	try:
		eventNameL = ret_dict["EventL"]
	except:
		print("No Events Found")
		eventNameL=[]
