#!/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.
#
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:
                        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
