#
# 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.
#
# Author: Larry Pearce
# Revised by: Larry Pearce
# Revision History
# Date         Change                                 By
# 2020-10-13   Original code (1.0)                    Larry Pearce

import os
import apex_sdk

# .NET references
import System
import System.Windows.Controls as WPFControls


# setting pre-defined properties of tool_propertyContainer
def getUIContent():
    my_toolProperty = apex_sdk.ToolPropertyContainer()

    my_toolProperty.TitleText = "Update Cbush Stiffness 1.0"

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

    my_toolProperty.WorkFlowInstructions = """<HTML><BODY><P STYLE=\"font-size:10;\"><SPAN>Update CBUSH stiffnesses</SPAN></P>
    <P><SPAN>This routine updates the CBUSH stiffness values.  If other CBUSH data such as damping is defined, it will be lost.</SPAN></P>
    <P><SPAN> </SPAN></P>
    <P STYLE=\"font-size:10;\"><SPAN>Send questions, comments and Elvis sightings to larry.pearce@mscsoftware.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, 20, 2)

    iRow = 0
    iCol = 0

    global stiffnessComboBox, stiffnessComboTextBlock
    global stiffToggles, stiffTextBoxes


    global matlComboBox,    matlComboTextBlock
    global diameterTextBox, diameterTextBlock


    stiffnessComboTextBlock = createTextBlock(my_Grid, "Update Method:", iRow, 0)
    stiffnessComboBox = createComboBox(my_Grid, iRow, 1)

    updateComboBox(stiffnessComboBox, ["Direct Input", "Nastran QRG"])

    stiffnessComboBox.SelectionChanged += comboBoxCallback

    iRow += 1

    iRow_save = iRow

    stiffToggles   = []
    stiffTextBoxes = []
    stiffToggles.append(createCheckBox(my_Grid, "Kx", iRow, 0))
    stiffTextBoxes.append(createTextBox(my_Grid, "", iRow, 1))
    iRow += 1
    stiffToggles.append(createCheckBox(my_Grid, "Ky", iRow, 0))
    stiffTextBoxes.append(createTextBox(my_Grid, "", iRow, 1))
    iRow += 1
    stiffToggles.append(createCheckBox(my_Grid, "Kz", iRow, 0))
    stiffTextBoxes.append(createTextBox(my_Grid, "", iRow, 1))
    iRow += 1
    stiffToggles.append(createCheckBox(my_Grid, "KRx", iRow, 0))
    stiffTextBoxes.append(createTextBox(my_Grid, "", iRow, 1))
    iRow += 1
    stiffToggles.append(createCheckBox(my_Grid, "KRy", iRow, 0))
    stiffTextBoxes.append(createTextBox(my_Grid, "", iRow, 1))
    iRow += 1
    stiffToggles.append(createCheckBox(my_Grid, "KRz", iRow, 0))
    stiffTextBoxes.append(createTextBox(my_Grid, "", iRow, 1))
    iRow += 1

    for toggle in stiffToggles:
        toggle.Checked   += stiffToggleCheck
        toggle.Unchecked += stiffToggleUnCheck

    for box in stiffTextBoxes:
        box.Visibility = System.Windows.Visibility.Collapsed

    iRow = iRow_save

    matlComboTextBlock = createTextBlock(my_Grid, "Material:", iRow, 0)
    matlComboBox       = createComboBox(my_Grid, 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)

    diameterTextBlock = createTextBlock(my_Grid, "Diameter:", iRow, 0)
    diameterTextBox   = createTextBox(my_Grid,   "",              iRow, 1)
    iRow += 1

    matlComboTextBlock.Visibility = System.Windows.Visibility.Collapsed
    matlComboBox.Visibility       = System.Windows.Visibility.Collapsed

    diameterTextBlock.Visibility = System.Windows.Visibility.Collapsed
    diameterTextBox.Visibility   = System.Windows.Visibility.Collapsed

    return my_Grid


def comboBoxCallback(sender, event):
    global stiffnessComboBox
    global stiffToggles, stiffTextBoxes

    global updateMaterialToggle
    global updateDiameterToggle
    global matlComboBox, matlComboTextBlock
    global diameterTextBox, diameterTextBlock

    choices = stiffnessComboBox.SelectedValue.ToString().split(":")
    choice = choices[len(choices)-1].lstrip().rstrip()

    if choice == "Nastran QRG":
        for item in enumerate(stiffToggles):
            stiffToggles[item[0]].Visibility   = System.Windows.Visibility.Collapsed
            stiffTextBoxes[item[0]].Visibility = System.Windows.Visibility.Collapsed

        matlComboTextBlock.Visibility = System.Windows.Visibility.Visible
        matlComboBox.Visibility       = System.Windows.Visibility.Visible
        diameterTextBlock.Visibility = System.Windows.Visibility.Visible
        diameterTextBox.Visibility   = System.Windows.Visibility.Visible
    else:
        matlComboTextBlock.Visibility = System.Windows.Visibility.Collapsed
        matlComboBox.Visibility       = System.Windows.Visibility.Collapsed

        diameterTextBlock.Visibility = System.Windows.Visibility.Collapsed
        diameterTextBox.Visibility   = System.Windows.Visibility.Collapsed
        for item in enumerate(stiffToggles):
            item[1].Visibility = System.Windows.Visibility.Visible
            if item[1].IsChecked:
                stiffTextBoxes[item[0]].Visibility = System.Windows.Visibility.Visible


def stiffToggleCheck(sender, event):
    global stiffToggles, stiffTextBoxes

    # i wish i could get sender to work the way i think it should

    for item in enumerate(stiffToggles):
        if item[1].IsChecked:
            stiffTextBoxes[item[0]].Visibility = System.Windows.Visibility.Visible
        else:
            stiffTextBoxes[item[0]].Visibility = System.Windows.Visibility.Collapsed


def stiffToggleUnCheck(sender, event):
    global stiffToggles, stiffTextBoxes

    for item in enumerate(stiffToggles):
        if item[1].IsChecked:
            stiffTextBoxes[item[0]].Visibility = System.Windows.Visibility.Visible
        else:
            stiffTextBoxes[item[0]].Visibility = System.Windows.Visibility.Collapsed


def createCheckBox(parent, label, row, col):

    checkBox = WPFControls.CheckBox()
    checkBox.Content = label
    checkBox.Margin = System.Windows.Thickness(5.)

    WPFControls.Grid.SetRow(checkBox, row)
    WPFControls.Grid.SetColumn(checkBox, col)

    parent.Children.Add(checkBox)

    return checkBox


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


# 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)

    return pickChoices


@apex_sdk.errorhandler
def HandleApplyButton():
    # Create a Dictionary to store the user defined tool data
    dictionary = {}

    choices = stiffnessComboBox.SelectedValue.ToString().split(":")
    choice = choices[len(choices)-1].lstrip().rstrip()
    dictionary["stiffnessMethod"] = choice

    if choice == "Direct Input":
        for item in enumerate(stiffToggles):
            if item[1].IsChecked:
                dictionary[str(item[0])+"_val"]    = stiffTextBoxes[item[0]].Text
                dictionary[str(item[0])+"_toggle"] = "True"
            else:
                dictionary[str(item[0])+"_val"]    = "0.0"
                dictionary[str(item[0])+"_toggle"] = "False"
        dictionary["material"] = ""
        dictionary["diameter"] = ""
    else:
        for item in enumerate(stiffToggles):
            dictionary[str(item[0])+"_val"]    = "0.0"
            dictionary[str(item[0])+"_toggle"] = "False"

        choices = matlComboBox.SelectedValue.ToString().split(":")
        choice = choices[len(choices)-1].lstrip().rstrip()
        dictionary["material"] = choice

        dictionary["diameter"] = diameterTextBox.Text


    file_path = os.path.dirname(os.path.realpath(__file__))
    script_path= os.path.join(file_path, 'auUpdateCBUSH.py')

    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 getMatls():
    global matlComboBox

    ret_dict = apex_sdk.getScriptFunctionReturnData()

    matls = ret_dict["matlList"]

    updateComboBox(matlComboBox, matls)

