# encoding: utf-8
"""
bgp.py

Created by Thomas Mangin on 2012-07-08.
Copyright (c) 2009-2017 Exa Networks. All rights reserved.
License: 3-clause BSD. (See the COPYRIGHT file)
"""

from struct import pack
from struct import unpack

from exabgp.util import hexstring


# =========================================================== RouteDistinguisher
# RFC 4364


class RouteDistinguisher(object):
    def __init__(self, rd):
        self.rd = rd
        self._len = len(self.rd)

    def __eq__(self, other):
        return self.rd == other.rd

    def __neq__(self, other):
        return self.rd != other.rd

    def __lt__(self, other):
        raise RuntimeError('comparing RouteDistinguisher for ordering does not make sense')

    def __le__(self, other):
        raise RuntimeError('comparing RouteDistinguisher for ordering does not make sense')

    def __gt__(self, other):
        raise RuntimeError('comparing RouteDistinguisher for ordering does not make sense')

    def __ge__(self, other):
        raise RuntimeError('comparing RouteDistinguisher for ordering does not make sense')

    def pack(self):
        return self.rd

    def __len__(self):
        return self._len

    def _str(self):
        t, c1, c2, c3 = unpack('!HHHH', self.rd)
        if t == 0:
            rd = '%d:%d' % (c1, (c2 << 16) + c3)
        elif t == 1:
            rd = '%d.%d.%d.%d:%d' % (c1 >> 8, c1 & 0xFF, c2 >> 8, c2 & 0xFF, c3)
        elif t == 2:
            rd = '%d:%d' % ((c1 << 16) + c2, c3)
        else:
            rd = hexstring(self.rd)
        return rd

    def json(self):
        if not self.rd:
            return ''
        return '"rd": "%s"' % self._str()

    def __hash__(self):
        return hash(self.rd)

    def __repr__(self):
        if not self.rd:
            return ''
        return ' rd %s' % self._str()

    @classmethod
    def unpack(cls, data):
        return cls(data[:8])

    # DO NOT USE, the right function is route_distinguisher() in exabgp.configuation.static.mpls
    @classmethod
    def fromElements(cls, prefix, suffix):
        try:
            if '.' in prefix:
                data = [bytes([0, 1])]
                # can be simplied
                data.extend([bytes([int(_)]) for _ in prefix.split('.')])
                data.extend([bytes([suffix >> 8]), bytes([suffix & 0xFF])])
                distinguisher = b''.join(data)
            else:
                number = int(prefix)
                if number < pow(2, 16) and suffix < pow(2, 32):
                    distinguisher = bytes([0, 0]) + pack('!H', number) + pack('!L', suffix)
                elif number < pow(2, 32) and suffix < pow(2, 16):
                    distinguisher = bytes([0, 2]) + pack('!L', number) + pack('!H', suffix)
                else:
                    raise ValueError('invalid route-distinguisher %s' % number)

            return cls(distinguisher)
        except ValueError:
            raise ValueError('invalid route-distinguisher %s:%s' % (prefix, suffix))


RouteDistinguisher.NORD = RouteDistinguisher(b'')
