import sys
import logging
import time
import itertools

from opcua import Client
from opcua import ua
from opcua.common.node import Node


class SubHandler(object):

    """
    Subscription Handler. To receive events from server for a subscription
    data_change and event methods are called directly from receiving thread.
    Do not do expensive, slow or network operation there. Create another 
    thread if you need to do such a thing
    """

    def datachange_notification(self, node, val, data):
        print("New data change", node, str(val))

    def event_notification(self, event):
        print("New event", event)

def browse(node):
    result = node.get_children()
    print()
    print("Children of node '" + node.get_display_name().Text + "':")
    if len(result) > 0:
        for tmp, i in zip(result, range(len(result))):
            name = tmp.get_display_name()
            nodeClass = tmp.get_node_class()
            print(i, "\t", name.Text, "("+ nodeClass.name + ")")
        action = int(input("Select action: 1 to select a specific node, 2 to browse a specific node [2]: ") or "2")
        if action == 1 :
            index = int(input("Specify node to select [0]: ") or "0")
            return result[index]
        if action == 2:
            index = int(input("Specify node to browse [0]: ") or "0")
            return browse(result[index])
    else:
        print("No children for node '", node.get_display_name().Text, "' available")
        return None




if __name__ == "__main__":
    url = input("Please specify the URL of the OPC UA server. [opc.tcp://localhost:4840]: ") or "opc.tcp://localhost:4840"
    client = Client(url)
    try:
        client.connect()

        root = client.get_root_node();

        print("Please selct node to subscribe")
        toSubscribe = browse(root)

        print("Node", toSubscribe.get_display_name().Text, "will be added to a subscription")
        
        handler = SubHandler()
        sub = client.create_subscription(500, handler)
        handle = sub.subscribe_data_change(toSubscribe)

        input("Please press key to exit")
    finally:
        client.disconnect()