import ipaddress
import json

from flask import Blueprint, Response, jsonify

from inventory_provider.routes import common

routes = Blueprint("inventory-data-classifier-support-routes", __name__)


@routes.route("/trap-metadata/<source_equipment>/<path:interface>",
              methods=['GET', 'POST'])
@common.require_accepts_json
def get_trap_metadata(source_equipment, interface):
    r = common.get_redis()

    cache_key = 'classifier:cache:%s:%s' % (source_equipment, interface)
    result = r.get(cache_key)

    if result:
        result = result.decode('utf-8')
    else:
        result = {}

        services = r.get(
            'opsdb:interface_services:%s:%s' % (source_equipment, interface))
        if services:
            result['services'] = json.loads(services.decode('utf=8'))

        ifc_info = r.get(
            'netconf-interfaces:%s:%s' % (source_equipment, interface))
        if ifc_info:
            result['interface'] = json.loads(ifc_info.decode('utf-8'))

        if not result:
            return Response(
                response="no available info for {} {}".format(
                    source_equipment, interface),
                status=404,
                mimetype="text/html")

        result = json.dumps(result)
        # cache this data for the next call
        r.set(cache_key, result.encode('utf-8'))

    return Response(result, mimetype="application/json")


@routes.route("/peer-info/<address>", methods=['GET', 'POST'])
@common.require_accepts_json
def peer_info(address):

    def _related_ix_peers(ix_public_peer_info):
        """
        TODO: this is probably the least efficient way of doing this
              (if it's a problem, pre-compute these lists)

        :param ix_public_peer_info: ix public peer info loaded for address
        :return:
        """

        protocol = type(ipaddress.ip_address(address)).__name__

        description = ix_public_peer_info['description']
        assert description is not None  # sanity: at least empty string
        keyword = description.split(' ')[0]  # regex needed??? (e.g. tabs???)

        r = common.get_redis()

        for k in r.keys('ix_public_peer:*'):
            peer = r.get(k.decode('utf-8')).decode('utf-8')
            peer = json.loads(peer)
            assert peer['description'] is not None  # sanity: as above...
            if not peer['description'].startswith(keyword):
                continue
            if peer['name'] == address:
                continue  # skip self
            peer_address = ipaddress.ip_address(peer['name'])
            if protocol == type(peer_address).__name__:
                yield peer['name']

    r = common.get_redis()

    result = {}

    info = r.get('ix_public_peer:%s' % address)
    if info:
        info = info.decode('utf-8')
        result['ix-public-peer-info'] = json.loads(info)
        result['ix-public-peer-group'] = list(
            _related_ix_peers(result['ix-public-peer-info']))

    info = r.get('vpn_rr_peer:%s' % address)
    if info:
        info = info.decode('utf-8')
        result['vpn-rr-peer-info'] = json.loads(info)

    if not result:
        return Response(
            response='no peering info found for %s' % address,
            status=404,
            mimetype="text/html")

    return jsonify(result)