#
# 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 - User Defined Tools using Python Scripts
# Assembly Part Tree View script to be called by Assembly Part Tree View UI Example
# 


def prepare_assembly_part_tree_view(dictionary=None):
    if dictionary is None:
        dictionary = {}
    import apex

    # Disable showing output dialog at the end
    apex.disableShowOutput()

    model = apex.currentModel()
    model_tree = process_assembly(model)
    print_model_tree(model_tree)

    return model_tree

# Get the node and element counts from the Assembly
def process_assembly(assembly):
    assembly_dict = {}
    assembly_dict["name"] = assembly.name
    assembly_dict["node_count"] = getTotalNodesCountFromAssembly(assembly)
    assembly_dict["element_count"] = getTotalElementsCountFromAssembly(assembly)
    sub_assembly_dicts = []
    part_dicts = []
    for sub_assembly in assembly.assemblies:
        sub_assembly_dicts.append(process_assembly(sub_assembly))
    for part in assembly.parts:
        part_dicts.append(process_part(part))
    assembly_dict["sub_assembies"] = sub_assembly_dicts
    assembly_dict["parts"] = part_dicts

    return assembly_dict

# Get the node and element counts from the Part
def process_part(part):
    part_dict={}
    part_dict["name"] = part.name
    part_dict["node_count"] = getTotalNodesCountFromPart(part)
    part_dict["element_count"] = getTotalElementsCountFromPart(part)
    return part_dict

# Count total nodes from all entities under assembly
def getTotalNodesCountFromAssembly(assembly):
    nodes = 0
    for part in assembly.parts:
        nodes += getTotalNodesCountFromPart(part)
    return nodes

# Count total elements from all entities under assembly
def getTotalElementsCountFromAssembly(assembly):
    nodes = 0
    for part in assembly.parts:
        nodes += getTotalElementsCountFromPart(part)
    return nodes

# Count total nodes from all entities under part
def getTotalNodesCountFromPart(part):
    nodes = 0
    for entity in part.meshes:
        nodes += entity.nodes.len()
    return nodes

# Count total elements from all entities under part
def getTotalElementsCountFromPart(part):
    elements = 0
    for entity in part.meshes:
        elements += entity.elements.len()
    return elements

def print_model_tree(model_tree):
    if "name" in model_tree:
        print(model_tree["name"], model_tree["node_count"], model_tree["element_count"])
        if "sub_assembies" in model_tree:
            for assembly_tree in model_tree["sub_assembies"]:
                print_model_tree(assembly_tree)
        if "parts" in model_tree:
            for part in model_tree["parts"]:
                print(part["name"], part["node_count"], part["element_count"])




