#!/usr/bin/python

import requests
import json
import random
from sets import Set


#
# Creates client-side connectivity json
#
def tapi_client_input(sip_uuids):
    create_input = {
              "tapi-connectivity:input": {
                "end-point" : [
                  {
                    "local-id": sip_uuids[0],
                    "service-interface-point": {
                        "service-interface-point-uuid" : sip_uuids[0]
                    }
                  },
                  {
                    "local-id": sip_uuids[1],
                    "service-interface-point": {
                        "service-interface-point-uuid" : sip_uuids[1]
                    }
                  }
                ]
              }
            }
    return create_input


#
# Creates line-side connectivity json
#
def tapi_line_input(sip_uuids):
    create_input = {
      "tapi-connectivity:input" : {
         "end-point": [
            {
               "layer-protocol-qualifier": "tapi-photonic-media:PHOTONIC_LAYER_QUALIFIER_NMC",
               "role": "UNKNOWN",
               "local-id": "Src_end_point",
               "direction": "BIDIRECTIONAL",
               "service-interface-point": {
                  "service-interface-point-uuid" : sip_uuids[0]
               },
               "protection-role": "WORK",
               "layer-protocol-name": "PHOTONIC_MEDIA"
            },
            {
               "direction": "BIDIRECTIONAL",
               "service-interface-point": {
                  "service-interface-point-uuid": sip_uuids[1]
               },
               "protection-role": "WORK",
               "layer-protocol-name": "PHOTONIC_MEDIA",
               "layer-protocol-qualifier": "tapi-photonic-media:PHOTONIC_LAYER_QUALIFIER_NMC",
               "role": "UNKNOWN",
               "local-id": "Dst_end_point"
            }
         ]
      }
    }
    return create_input


#
# Obtains TAPI context through restconf
#
def get_context(url_context):
    resp = requests.get(url_context, auth=('onos', 'rocks'))
    if resp.status_code != 200:
        raise Exception('GET {}'.format(resp.status_code))
    return resp.json()


#
# Check if the node is transponder.
# True  - transponder
# False - OLS
#
def is_transponder_node(node):
    if len(node["owned-node-edge-point"]) > 0 and "mapped-service-interface-point" in node["owned-node-edge-point"][0]:
        return True
    else:
        return False


#
# Parse src and dst sip-uuids of specific link from topo.
# The ports should be line side but not client side.
#
def parse_src_dst(topo, link_index=-1):
    if link_index == -1:
        # select a link randomly from all links of topo
        link_index = random.randint(0, len(topo["link"]) - 1)
    nep_pair = topo["link"][link_index]["node-edge-point"]
    assert topo["uuid"] == nep_pair[0]["topology-uuid"]
    assert topo["uuid"] == nep_pair[1]["topology-uuid"]
    src_onep, dst_onep = (find_line_onep(nep_pair[0], topo["node"]),
                          find_line_onep(nep_pair[1], topo["node"]))
    if src_onep is not None and dst_onep is not None:
        # If the link is between two transponders directly
        pass
    elif src_onep is None and dst_onep is None:
        raise AssertionError("Impossible for that both two ports are OLS port")
    else:
        # If one of src_onep and dst_onep is None, then make src_onep not None,
        # and find a new dst_onep with same connection id.
        if src_onep is None:
            src_onep = dst_onep
            dst_onep = None
        conn_id = parse_value(src_onep["name"])["odtn-connection-id"]
        for node in topo["node"]:
            cep = src_onep["tapi-connectivity:cep-list"]["connection-end-point"]
            assert len(cep) == 1
            if cep[0]["parent-node-edge-point"]["node-uuid"] != node["uuid"] and is_transponder_node(node):
                # If this node is not the node that includes src_onep, and not a OLS node
                for onep in node["owned-node-edge-point"]:
                    if parse_value(onep["name"])["odtn-connection-id"] == conn_id\
                            and parse_value(onep["name"])["odtn-port-type"] == "line":
                        dst_onep = onep
                        break
            if dst_onep is not None:
                break

    src_sip_uuid, dst_sip_uuid = \
        (src_onep["mapped-service-interface-point"][0]["service-interface-point-uuid"],
         dst_onep["mapped-service-interface-point"][0]["service-interface-point-uuid"])

    return src_onep, dst_onep, src_sip_uuid, dst_sip_uuid


#
# Check whether the sip uuid is used in other existed services.
#
def is_port_used(sip_uuid, conn_context):
    try:
        for service in conn_context["connectivity-service"]:
            for id in [0, 1]:
                if service["end-point"][id]["service-interface-point"]["service-interface-point-uuid"] == sip_uuid:
                    return True
    except KeyError:
        print "There is no line-side service in ONOS now."
    return False


#
# Requests a connectivity service
#
def request_connection(url_connectivity, context):
    # All Context SIPs
    sips = context["tapi-common:context"]["service-interface-point"]

    # Sorted Photonic Media SIPs. filter is an iterable
    esips = list(filter(is_dsr_media, sorted(sips, key=lambda sip: sip["name"][0]["value"])))
    endpoints = [esips[0], esips[-1]]
    sip_uuids = []
    for sip in endpoints:
        sip_uuids.append(sip["uuid"])
    for uuid in sip_uuids:
        print(uuid)

    create_input_json = json.dumps(tapi_client_input(sip_uuids))
    print (create_input_json)
    headers = {'Content-type': 'application/json'}
    resp = requests.post(url_connectivity, data=create_input_json, headers=headers,  auth=('onos', 'rocks'))
    if resp.status_code != 200:
        raise Exception('POST {}'.format(resp.status_code))
    return resp


#
# Filter method used to keep only SIPs that are photonic_media
#
def is_photonic_media(sip):
    return sip["layer-protocol-name"] == "PHOTONIC_MEDIA"


#
# Filter method used to keep only SIPs that are DSR
#
def is_dsr_media(sip):
    return sip["layer-protocol-name"] == "DSR"


#
# Processes the topology to verify the correctness
#
def process_topology():
   # TODO use method to parse topology
   # Getting the Topology
   # topology = context["tapi-common:context"]["tapi-topology:topology-context"]["topology"][0]
   # nodes = topology["node"];
   # links = topology["link"];
   noop


#
# Find mapped client-side sip_uuid according to a line-side sip_uuid.
# connection-ids of these two owned-node-edge-point should be the same.
#
def find_mapped_client_sip_uuid(line_sip_uuid, nodes):
    line_node = None
    line_onep = None
    for node in nodes:
        if is_transponder_node(node):
            for onep in node["owned-node-edge-point"]:
                if onep["mapped-service-interface-point"][0]["service-interface-point-uuid"] == line_sip_uuid:
                    line_node = node
                    line_onep = onep
                    break
    if line_node is None:
        raise AssertionError("Cannot match line-side sip uuid in topology.")
    conn_id = parse_value(line_onep["name"])["odtn-connection-id"]
    for onep in line_node["owned-node-edge-point"]:
        vals = parse_value(onep["name"])
        if vals["odtn-connection-id"] == conn_id and vals["odtn-port-type"] == "client":
            return onep["mapped-service-interface-point"][0]["service-interface-point-uuid"], vals
    return None


#
# Create a client-side connection. Firstly, get the context, parsing for SIPs that connect
# with each other in line-side; Secondly, issue the request
#
def create_client_connection(url_context, url_connectivity):
    headers = {'Content-type': 'application/json'}
    context = get_context(url_context)
    # select the first topo from all topologies
    topo = context["tapi-common:context"]["tapi-topology:topology-context"]["topology"][0]
    # Gather all current used sip_uuids
    used_sip_uuids = Set()
    try:
        services = context["tapi-common:context"]["tapi-connectivity:connectivity-context"]["connectivity-service"]
        for service in services:
            used_sip_uuids.add(service["end-point"][0]["service-interface-point"]["service-interface-point-uuid"])
            used_sip_uuids.add(service["end-point"][1]["service-interface-point"]["service-interface-point-uuid"])
    except KeyError:
        print "There is no existed connectivity service inside ONOS."

    # select the first available line-side service as bridge. If there is no available line-side service,
    # then only create a client-to-client service for src and dst node.
    empty_client_src_sip_uuid, empty_client_dst_sip_uuid = None, None
    empty_src_name, empty_dst_name, empty_client_src_name, empty_client_dst_name = None, None, None, None
    for link_index in range(0, len(topo["link"])):
        src_onep, dst_onep, src_sip_uuid, dst_sip_uuid = parse_src_dst(topo, link_index)
        client_src_sip_uuid, client_src_name = find_mapped_client_sip_uuid(src_sip_uuid, topo["node"])
        client_dst_sip_uuid, client_dst_name = find_mapped_client_sip_uuid(dst_sip_uuid, topo["node"])
        # firstly, check if line-side service exists
        # If line-side service exists
        if src_sip_uuid in used_sip_uuids and dst_sip_uuid in used_sip_uuids:
            # secondly, check if mapped client-side service exists
            if (client_src_sip_uuid not in used_sip_uuids) and (client_dst_sip_uuid not in used_sip_uuids):
                # If there is no such client-side connection exists
                # Create new client-side connection directly
                print "Create client-side connection between %s and %s." % \
                      (client_src_name["onos-cp"], client_dst_name["onos-cp"])
                create_input_json = json.dumps(tapi_client_input((client_src_sip_uuid, client_dst_sip_uuid)))
                resp = requests.post(url_connectivity, data=create_input_json, headers=headers,
                                     auth=('onos', 'rocks'))
                if resp.status_code != 200:
                    raise Exception('POST {}'.format(resp.status_code))
                return resp
            else:
                # If there exists such client-side connection
                # Do nothing, just continue
                pass
        else:
            # If line-side service doesn't exist
            # save 4 sip uuids, and continue
            empty_client_src_sip_uuid = client_src_sip_uuid
            empty_client_dst_sip_uuid = client_dst_sip_uuid
            empty_client_src_name = client_src_name
            empty_client_dst_name = client_dst_name
            empty_src_name = parse_value(src_onep["name"])
            empty_dst_name = parse_value(dst_onep["name"])
            pass

    # After FOR loop, if this method doesn't return, there is no available line-side
    # service for mapped client-side service creation.
    # So, we need to create two client-side services.
    if empty_client_src_sip_uuid is None:
        # None case means all client-side services exist.
        raise AssertionError("There is no available client-side service could be created.")
    else:
        print "Create client-side services:"
        print "\t- from %s to %s." % (empty_client_src_name["onos-cp"], empty_client_dst_name["onos-cp"])
        print "This service should go through:"
        print "\t- %s and %s." % (empty_src_name["onos-cp"], empty_dst_name["onos-cp"])
        create_input_json = json.dumps(tapi_client_input((empty_client_src_sip_uuid, empty_client_dst_sip_uuid)))
        resp = requests.post(url_connectivity, data=create_input_json, headers=headers,
                             auth=('onos', 'rocks'))
        if resp.status_code != 200:
            raise Exception('POST {}'.format(resp.status_code))
        return resp


#
# Parse array structure "name" under structure "owned node edge point"
#
def parse_value(arr):
    rtn = {}
    for item in arr:
        rtn[item["value-name"]] = item["value"]
    return rtn


#
# Find node edge point of node structure in topology with client-side port, by using nep with line-side port.
# The odtn-connection-id should be the same in both line-side nep and client-side nep
#
def find_client_onep(line_nep_in_link, nodes):
    for node in nodes:
        if node["uuid"] == line_nep_in_link["node-uuid"]:
            conn_id = None
            for onep in node["owned-node-edge-point"]:
                if onep["uuid"] == line_nep_in_link["node-edge-point-uuid"]:
                    name = parse_value(onep["name"])
                    if name["odtn-port-type"] == "line":
                        conn_id = name["odtn-connection-id"]
                        break
            if conn_id is None:
                raise AssertionError("Cannot find owned node edge point with node id %s and nep id %s."
                                     % (line_nep_in_link["node-uuid"], line_nep_in_link["node-edge-point-uuid"], ))
            for onep in node["owned-node-edge-point"]:
                name = parse_value(onep["name"])
                if name["odtn-port-type"] == "client" and name["odtn-connection-id"] == conn_id:
                    return onep

    return None


#
# Create a line-side connection. Firstly, get the context, parsing for SIPs with photonic_media type,
# and select one pair of them; Secondly, issue the request
#
def create_line_connection(url_context, url_connectivity):
    context = get_context(url_context)
    # select the first topo from all topologies
    topo = context["tapi-common:context"]["tapi-topology:topology-context"]["topology"][0]
    # select randomly the src_sip_uuid and dst_sip_uuid with same connection id.
    src_onep, dst_onep, src_sip_uuid, dst_sip_uuid = parse_src_dst(topo)
    while is_port_used(src_sip_uuid, context["tapi-common:context"]["tapi-connectivity:connectivity-context"]):
        print "Conflict occurs between randomly selected line-side link and existed ones."
        src_onep, dst_onep, src_sip_uuid, dst_sip_uuid = parse_src_dst(topo)

    print "\nBuild line-side connectivity:\n|Item|SRC|DST|\n|:--|:--|:--|\n|onos-cp|%s|%s|\n|connection id|%s|%s|\n|sip uuid|%s|%s|" % \
          (src_onep["name"][2]["value"], dst_onep["name"][2]["value"],
           src_onep["name"][1]["value"], dst_onep["name"][1]["value"],
           src_sip_uuid, dst_sip_uuid)
    create_input_json = json.dumps(tapi_line_input((src_sip_uuid, dst_sip_uuid)))
    print "\nThe json content of creation operation for line-side connectivity service is \n\t\t%s." % \
          create_input_json
    headers = {'Content-type': 'application/json'}
    resp = requests.post(url_connectivity, data=create_input_json, headers=headers, auth=('onos', 'rocks'))
    if resp.status_code != 200:
        raise Exception('POST {}'.format(resp.status_code))
    return resp


#
# find owned-node-edge-point from all nodes according to line_nep_in_links
#
def find_line_onep(line_nep_in_link, nodes):
    for node in nodes:
        if node["uuid"] == line_nep_in_link["node-uuid"]:
            if not is_transponder_node(node):
                break
            for onep in node["owned-node-edge-point"]:
                if onep["uuid"] == line_nep_in_link["node-edge-point-uuid"]:
                    # check the length equals 1 to verify the 1-to-1 mapping relationship
                    assert len(onep["mapped-service-interface-point"]) == 1
                    return onep
    # When node is OLS, this method will return None
    return None


#
# Obtains existing connectivity services
#
def get_connection(url_connectivity, uuid):
    # uuid is useless for this method
    json = '{}'
    headers = {'Content-type': 'application/json'}
    resp = requests.post(url_connectivity, data=json, headers=headers,  auth=('onos', 'rocks'))
    if resp.status_code != 200:
            raise Exception('POST {}'.format(resp.status_code))
    return resp
