
from pathlib import Path
from datetime import datetime
import subprocess

from ...core.bl_utils import get_bl_cmd
from ...core.lib_utils import get_asset_data, asset_library_map
from ...core.catalog import read_catalog
from ... import constants

import bpy
from bpy.types import Operator
from bpy.props import StringProperty, EnumProperty


class ASSETLIB_OT_update_nodes(Operator):
    bl_idname = 'assetlibrary.update_nodes'
    bl_label = 'Update node'
    bl_options = {"REGISTER", "UNDO"}

    selection : EnumProperty(items=[(s, s.title(), '') for s in ('ALL', 'SELECTED', 'CURRENT')], default="CURRENT", name='All Nodes')

    @classmethod
    def poll(cls, context):
        return context.space_data.edit_tree

    def invoke(self, context, event):
        return context.window_manager.invoke_props_dialog(self)

    def execute(self, context):
        asset_libraries = context.preferences.filepaths.asset_libraries

        ntree = context.space_data.edit_tree
        ntree_name = ntree.name
        new_ntree = None

        if self.selection == 'SELECTED':
            nodes = [ n.node_tree for n in context.space_data.edit_tree.nodes 
                                if n.type == "GROUP" and n.select]
        elif self.selection == 'CURRENT':
            active_node = context.space_data.edit_tree
            nodes = [active_node]
        else:
            nodes = list(bpy.data.node_groups)

        library_map = asset_library_map()
        
        #node_groups = list(bpy.data.node_groups)
        #images = list(bpy.data.images)
        #materials = list(bpy.data.materials)

        with remap_datablock_duplicates():

            for node in nodes:
                blend_file = find_asset_source(library_map, 'node_groups', node.name)
                link = bool(node.library)

                with bpy.data.libraries.load(str(blend_file), link=link) as (data_from, data_to):
                    data_to.node_groups = [node.name]

                for new_node_group in new_node_groups:
                    new_node_group_name = new_node_group.library_weak_reference.id_name[2:]
                    local_node_group = next((n for n in bpy.data.node_groups if n.name == new_node_group_name and n != new_node_group), None)

                    if not local_node_group:
                        print(f'No local node_group {new_node_group_name}')
                        continue
                    
                    print(f'Merge node {local_node_group.name} into {new_node_group.name}')

                    local_node_group.user_remap(new_node_group)
                    new_node_group.interface_update(context)
                    bpy.data.node_groups.remove(local_node_group)

                    new_node_group.name = new_node_group_name
                    new_node_group.asset_clear()


        node_names = set(n.name for n in nodes)

        for asset_library in asset_libraries:
            library_path = Path(asset_library.path)
            blend_files = [fp for fp in library_path.glob("**/*.blend") if fp.is_file()]

            node_groups = list(bpy.data.node_groups)# Storing original node_geoup to compare with imported

            link = (asset_library.import_method == 'LINK')
            for blend_file in blend_files:
                print(blend_file)
                with bpy.data.libraries.load(str(blend_file), assets_only=True, link=link) as (data_from, data_to):

                    import_node_groups = [n for n in data_from.node_groups if n in node_names]
                    print("import_node_groups", import_node_groups)
                    data_to.node_groups = import_node_groups

                    node_names -= set(import_node_groups) # Store already updated nodes

                new_node_groups = set(n for n in bpy.data.node_groups if n not in node_groups)

                for new_node_group in new_node_groups:
                    new_node_group_name = new_node_group.library_weak_reference.id_name[2:]
                    local_node_group = next((n for n in bpy.data.node_groups if n.name == new_node_group_name and n != new_node_group), None)

                    if not local_node_group:
                        print(f'No local node_group {new_node_group_name}')
                        continue
                    
                    print(f'Merge node {local_node_group.name} into {new_node_group.name}')

                    local_node_group.user_remap(new_node_group)
                    new_node_group.interface_update(context)
                    bpy.data.node_groups.remove(local_node_group)

                    new_node_group.name = new_node_group_name
                    new_node_group.asset_clear()


        return {'FINISHED'}


    def draw(self, context):
        layout = self.layout
        layout.prop(self, "selection", expand=True)


bl_classes = (
    ASSETLIB_OT_update_nodes,
)


def register():
    for bl_class in bl_classes:
        bpy.utils.register_class(bl_class)


def unregister():
    for bl_class in reversed(bl_classes):
        bpy.utils.unregister_class(bl_class)
