from asyncua import Client
import asyncio
import socket
from time import sleep
import struct
import json

nm_no = None

async def create_node_hierarchy(client, node_objects):
    node_hierarchy={}
    for sub_obj in node_objects:
        if("ns="+str(nm_no)+";" in str(sub_obj)):
            node = client.get_node(sub_obj)
            children_nodes = await node.get_children()
            identifier = str(children_nodes[0].nodeid.Identifier) if children_nodes else ""
            node_class = await sub_obj.read_node_class()
            if (identifier not in str(sub_obj)):
                child_disp_name = await sub_obj.read_display_name()
                identifier_name = sub_obj.nodeid.Identifier
                node_hierarchy[identifier_name] = await create_node_hierarchy(client, children_nodes)
                node_hierarchy[identifier_name]["name"] = child_disp_name.Text
                node_hierarchy[identifier_name]["type"] = node_class._value_
                if (node_class._name_ == "Variable"):
                    datatype = await sub_obj.read_data_type_as_variant_type()
                    node_hierarchy[identifier_name]["datatype"] = datatype._value_
            else:
                disp_name = await sub_obj.read_display_name()
                identifier_name = sub_obj.nodeid.Identifier
                node_hierarchy[identifier_name] = {}
                node_hierarchy[identifier_name]["name"] = disp_name.Text
                node_hierarchy[identifier_name]["type"] = node_class._value_
                if (node_class._name_ == "Variable"):
                    datatype = await sub_obj.read_data_type_as_variant_type()
                    node_hierarchy[identifier_name]["datatype"] = datatype._value_
    return node_hierarchy

async def get_send_hash(ENDPOINT,NAMESPACE,server_hash_udp_ip,server_hash_udp_port):
    global nm_no
    serverAddressPort = (server_hash_udp_ip, server_hash_udp_port)
    UDPClientSocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
    async with Client(url=ENDPOINT) as client:
        nm_no=await client.get_namespace_index(NAMESPACE)
        root_node = client.get_root_node()
        root_objects = await root_node.get_children()
        node_objects = root_objects[0]
        while True:
            node_objects_children = await node_objects.get_children()  # replace with your own node id
            node_hierarchy = await create_node_hierarchy(client, node_objects_children)
            node_hierarchy["hash"] = hash(str(node_hierarchy))
            node_hierarchy["namespace_idx"]=nm_no
            json_hierarchy = json.dumps(node_hierarchy)
            hierarchy=json.dumps(json_hierarchy)
            utf8_encoded_string = hierarchy.encode('utf-8')
            string_length = len(utf8_encoded_string)
            length_bytes = struct.pack("!I", string_length)
            binary_data = length_bytes + utf8_encoded_string
            print(binary_data)
            UDPClientSocket.sendto(binary_data, serverAddressPort)

def send_hash(Endpoint,Namespace,server_hash_udp_ip,server_hash_udp_port):
    asyncio.run(get_send_hash(Endpoint,Namespace,server_hash_udp_ip,server_hash_udp_port))