#
# 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.
#
# MSC Apex - Material Database Tool using Scripts
# coding: utf-8

# Author: Javier Lázaro
# Revised by: Javier Lázaro
# Revision History
# Date         Change                                 By
# 2020-11-25   Original code                          Javier Lázaro

#
import os
import apex_sdk

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

# Define current file path
current_file_path = os.path.dirname(os.path.realpath(__file__))
main_file = os.path.join(current_file_path, r"_MAIN_MyMaterials.py")

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

    # Provide an icon and a name for the tool property panel
    my_toolProperty.TitleImageUriString = os.path.join(os.path.dirname(current_file_path), r"res\icon.png")
    my_toolProperty.TitleText = "My Materials"

    # Define UI
    my_toolProperty.ToolPropertyContent = getCustomToolPropertyContent()

    my_toolProperty.WorkFlowInstructions = """<HTML><BODY><P STYLE=\"font-size:10;\"><SPAN>
    Save button allows you to change the database. Edit .xls file and save changes.\n
    </SPAN></P><SPAN><P>
    Apply button allows you to import the selected materials.\n
    </SPAN></P><SPAN><P>
    Units are fixed. Magnitudes displayed here are written in mm-t-s-N system. They will be converted to your current unit system on import.\n
    </SPAN></P><SPAN><P>
    Send questions, comments or suggestions to javier.lazaroortega@hexagon.com\n
    </SPAN></P></BODY></HTML>"""

    # handle apply button (green) click event
    my_toolProperty.AppliedCommand = apex_sdk.ActionCommand(System.Action(importSelected))
    # handle exit button (red) click event
    # my_toolProperty.ExitCommand = apex_sdk.ActionCommand(System.Action(HandleExitButton))

    return(my_toolProperty)


# Define Layout and Components
def getCustomToolPropertyContent():

    # Create a Grid
    global load_error
    global my_Grid
    # Create a Grid
    my_Grid = WPFControls.Grid()


    # Add Two Row and One Column
    my_Grid.RowDefinitions.Add(WPFControls.RowDefinition())
    my_Grid.RowDefinitions.Add(WPFControls.RowDefinition())
    my_Grid.ColumnDefinitions.Add(WPFControls.ColumnDefinition())

    #Create WrapPanel
    myWrapPanel = WPFControls.WrapPanel()
    myWrapPanel.Orientation=WPFControls.Orientation.Horizontal
    WPFControls.Grid.SetRow(myWrapPanel, 0)
    WPFControls.Grid.SetColumn(myWrapPanel, 0)
    #Create Button editXLS
    openXLSBtn = WPFControls.RadioButton()
    openXLSBtn.Width = 40
    openXLSBtn.Height = 40
    openXLSBtn.Opacity = 1.0
    openXLSBtn.Content = os.path.join(os.path.dirname(current_file_path), r"res\edit_icon.png")
    openXLSBtn.SetResourceReference(WPFControls.Control.StyleProperty, "IconOnlyRadioButton")
    openXLSBtn.Click+=openXLS
    myWrapPanel.Children.Add(openXLSBtn)
    # Add the WrapPanel to the Grid
    my_Grid.Children.Add(myWrapPanel)



    global xls, dataGrids, dataTables, my_tabControl
    ret = apex_sdk.runScriptFunction(main_file,"read_xls",callback=getXLS)

    dataGrids={}

    global my_tabControl
    my_tabControl = WPFControls.TabControl()

    # Add the tabControl to the Grid
    WPFControls.Grid.SetRow(my_tabControl, 1)
    WPFControls.Grid.SetColumn(my_tabControl, 0)
    my_Grid.Children.Add(my_tabControl)
    return my_Grid
def myGrid(sheet_name):

    global my_Grid
    global dataGrids

    # Create a Grid
    my_Grid = WPFControls.Grid()


    # Add Two Row and One Column
    my_Grid.RowDefinitions.Add(WPFControls.RowDefinition())
    my_Grid.ColumnDefinitions.Add(WPFControls.ColumnDefinition())

    # Create a DataGrid
    dataGrids[sheet_name] = WPFControls.DataGrid()
    # myDataGrid.IsEditable = False #This doesn't work, I don't know the attribute

    # Position the DataGrid in the first row, column of the Grid
    WPFControls.Grid.SetRow(dataGrids[sheet_name], 0)
    WPFControls.Grid.SetColumn(dataGrids[sheet_name], 0)
    dataGrids[sheet_name].Height = 300
    # dataGrids[sheet_name].HorizonatAlignment = "Streched"
    dataGrids[sheet_name].ItemsSource = dataTables[sheet_name].DefaultView

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

    # Return the Grid
    return my_Grid

def UpdateTabData(xls):

    global my_tabControl
    global dataTables
    global tabItems
    try:
        dataTables = generateDataTables()
        my_tabControl.Items.Clear()
        tabItems = []
        dataGrids = {}
        for sheet_name, materials in xls.items():
            # tabItem = WPFControls.TabItem()
            tabItems.append(WPFControls.TabItem())
            tabItems[-1].Header = sheet_name #borrar el iso u ortho
            tabItems[-1].AddChild(myGrid(sheet_name))
            # dataGrids[sheet_name] = myGrid(sheet_name)[1] #here the dataGrid is copied. Is not the displayed variable

            my_tabControl.AddChild(tabItems[-1])
    except:
        load_error=True
        print('Error loading tool!')
        # traceback.print_exc()
        pass

# Function to handle the openXLS Button
@apex_sdk.errorhandler
def openXLS(sender, args):

    xls = os.path.join(current_file_path, r"MyMaterials.xls")
    xls = '"'+xls+'"'
    os.system(xls)
    # apex_sdk.runScriptFunction(os.path.join(current_file_path, r"openXLS.py"),"read_xls", dictionary)
    apex_sdk.runScriptFunction(main_file,"read_xls",callback=getXLS)
    generateDataTables() #need to update the new data, but it doesnt work
@apex_sdk.errorhandler
def getXLS():
    global xls
    xls = apex_sdk.getScriptFunctionReturnData()
    UpdateTabData(xls)
    return xls

# Function to handle the importSelected Button
@apex_sdk.errorhandler
def importSelected():

    currentTab = getCurrentTab()

    matNames = []
    selectedMaterials = list(dataGrids[currentTab].SelectedItems)
    for mat in selectedMaterials:
        matNames.append(mat.get_Item(0))

    selectedMat_dict = {"matNames": matNames, "sheet": currentTab}
    # selectedMat_dict["len"] = my_tabControl.GetChildrenCount()

    if "Iso" in currentTab:
        apex_sdk.runScriptFunction(main_file,"importSelectedIso", selectedMat_dict)
    elif "Ortho" in currentTab:
        apex_sdk.runScriptFunction(main_file,"importSelectedOrtho", selectedMat_dict)


#This function receives data from the Script API function and updates the Tool UI

def generateDataTables():

    dataTables = {}

    for sheet_name, materials in xls.items():
        # Create parts table
        data_table = WPFData.DataTable("Part Contents")

        AddRows = []
        if "Iso" in sheet_name:
            data_table.Columns.Add("Name")
            data_table.Columns.Add("E")
            data_table.Columns.Add("Nu")
            data_table.Columns.Add("Rho")
            data_table.Columns.Add("TEC")
            # Hide this columns in Apex Table (still readen from .xls) so it is not too big
            #     Careful for small resolution (1360x768 or lower), e.g. for projectors, it may not fit the window and crush Apex...
            # data_table.Columns.Add("SDC")
            # data_table.Columns.Add("Tens")
            # data_table.Columns.Add("Comp")
            # data_table.Columns.Add("Shear")

            # Add data to the table for each part

            for index, material in materials.items():
                # If you are not hiding Failure Columns:
                # AddRows = list(material.values())

                # If you are hiding Failure Columns:
                AddRows = list(material.values())[0:5]
                data_table.Rows.Add(AddRows)

            # Set the ItemsSource for the data grid to the DataTable
            # dataGrids[sheet_name].ItemsSource = data_table.DefaultView
            dataTables[sheet_name] = data_table
        elif "Ortho" in sheet_name:
            data_table.Columns.Add("Name")
            data_table.Columns.Add("Ex")
            data_table.Columns.Add("Ey")
            data_table.Columns.Add("Gxy")
            data_table.Columns.Add("Gyz")
            data_table.Columns.Add("Gzx")
            data_table.Columns.Add("NUxy")
            data_table.Columns.Add("Rho")
            data_table.Columns.Add("TECx")
            data_table.Columns.Add("TECy")
            # Hide this columns in Apex Table (still readen from .xls) so it is not too big
            #     Careful for small resolution (1360x768 or lower), e.g. for projectors, it may not fit the window and crush Apex...
            # data_table.Columns.Add("SDC")
            # data_table.Columns.Add("TX")
            # data_table.Columns.Add("TY")
            # data_table.Columns.Add("CX")
            # data_table.Columns.Add("CY")
            # data_table.Columns.Add("S")

            # Add data to the table for each part

            for index, material in materials.items():
                # If you are not hiding Failure Columns:
                # AddRows = list(material.values())

                # If you are hiding Failure Columns:
                AddRows = list(material.values())[0:10]

                data_table.Rows.Add(AddRows)

            # Set the ItemsSource for the data grid to the DataTable
            # dataGrids[sheet_name].ItemsSource = data_table.DefaultView
            dataTables[sheet_name] = data_table

    return dataTables

def getCurrentTab():
    for tab in tabItems:
        if tab.IsSelected:
            return tab.Header
