"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.

SPDX-License-Identifier: Apache-2.0 OR MIT
"""
import uuid,  os
import azlmbr.scene as sceneApi
import azlmbr.scene.graph
from scene_api import scene_data as sceneData

def get_mesh_node_names(sceneGraph):
    meshDataList = []
    node = sceneGraph.get_root()
    children = []

    while node.IsValid():
        # store children to process after siblings
        if sceneGraph.has_node_child(node):
            children.append(sceneGraph.get_node_child(node))

        # store any node that has mesh data content
        nodeContent = sceneGraph.get_node_content(node)
        if nodeContent is not None and nodeContent.CastWithTypeName('MeshData'):
            if sceneGraph.is_node_end_point(node) is False:
                nodeName = sceneData.SceneGraphName(sceneGraph.get_node_name(node))
                nodePath = nodeName.get_path()
                if (len(nodeName.get_path())):
                    meshDataList.append(sceneData.SceneGraphName(sceneGraph.get_node_name(node)))

        # advance to next node
        if sceneGraph.has_node_sibling(node):
            node = sceneGraph.get_node_sibling(node)
        elif children:
            node = children.pop()
        else:
            node = azlmbr.scene.graph.NodeIndex()

    return meshDataList

def update_manifest(scene):
    graph = sceneData.SceneGraph(scene.graph)
    meshNameList = get_mesh_node_names(graph)
    sceneManifest = sceneData.SceneManifest()
    sourceFilenameOnly = os.path.basename(scene.sourceFilename)
    sourceFilenameOnly = sourceFilenameOnly.replace('.','_')

    for activeMeshIndex in range(len(meshNameList)):
        chunkName = meshNameList[activeMeshIndex]
        chunkPath = chunkName.get_path()
        meshGroupName = '{}_{}'.format(sourceFilenameOnly, chunkName.get_name())
        meshGroup = sceneManifest.add_mesh_group(meshGroupName)
        meshGroup['id'] = '{' + str(uuid.uuid5(uuid.NAMESPACE_DNS, sourceFilenameOnly + chunkPath)) + '}'
        sceneManifest.mesh_group_add_comment(meshGroup, 'auto generated by scene manifest')
        sceneManifest.mesh_group_add_advanced_coordinate_system(meshGroup, None, None, None, 1.0)
        sceneManifest.mesh_group_select_node(meshGroup, chunkPath)

    return sceneManifest.export()

mySceneJobHandler = None

def on_update_manifest(args):
    scene = args[0]
    result = update_manifest(scene)
    global mySceneJobHandler
    # do not delete or set sceneJobHandler to None, just disconnect from it.
    # this call is occuring while the scene Job Handler itself is in the callstack, so deleting it here
    # would cause a crash.
    mySceneJobHandler.disconnect()
    return result

def main():
    global mySceneJobHandler
    mySceneJobHandler = sceneApi.ScriptBuildingNotificationBusHandler()
    mySceneJobHandler.connect()
    mySceneJobHandler.add_callback('OnUpdateManifest', on_update_manifest)

if __name__ == "__main__":
    main()