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

nm_no = None

class Hash_Sender():
    def __init__(self):
        self.hash = ""

    async def create_node_hierarchy(self,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 self.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(self,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 self.create_node_hierarchy(client, node_objects_children)
                self.hash = node_hierarchy["hash"] = hash(str(node_hierarchy))
                node_hierarchy["namespace_idx"]=nm_no
                json_hierarchy = json.dumps(node_hierarchy)
                binary_data = json_hierarchy.encode()
                UDPClientSocket.sendto(binary_data, serverAddressPort)

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