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

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

from struct import unpack
from struct import error

from exabgp.util import character
from exabgp.util import concat_bytes
from exabgp.protocol.family import AFI
from exabgp.protocol.family import SAFI
from exabgp.bgp.message.message import Message
from exabgp.bgp.message.notification import Notify

# =================================================================== Notification
# A Notification received from our peer.
# RFC 4271 Section 4.5


class Reserved(int):
    def __str__(self):
        if self == 0:
            return 'query'
        if self == 1:
            return 'begin'
        if self == 2:
            return 'end'
        return 'invalid'


@Message.register
class RouteRefresh(Message):
    ID = Message.CODE.ROUTE_REFRESH
    TYPE = character(Message.CODE.ROUTE_REFRESH)

    request = 0
    start = 1
    end = 2

    def __init__(self, afi, safi, reserved=0):
        self.afi = AFI.create(afi)
        self.safi = SAFI.create(safi)
        self.reserved = Reserved(reserved)

    def message(self, negotiated=None):
        return self._message(concat_bytes(self.afi.pack(), character(self.reserved), self.safi.pack()))

    def __str__(self):
        return "REFRESH"

    def extensive(self):
        return 'route refresh %s/%d/%s' % (self.afi, self.reserved, self.safi)

    # XXX: Check how we get this data into the RR
    # def families (self):
    # 	return self._families[:]

    @classmethod
    def unpack_message(cls, data, direction=None, negotiated=None):
        try:
            afi, reserved, safi = unpack('!HBB', data)
        except error:
            raise Notify(7, 1, 'invalid route-refresh message')
        if reserved not in (0, 1, 2):
            raise Notify(7, 2, 'invalid route-refresh message subtype')
        return RouteRefresh(afi, safi, reserved)

    def __eq__(self, other):
        if not isinstance(other, RouteRefresh):
            return False
        if self.afi != other.afi:
            return False
        if self.safi != other.safi:
            return False
        if self.reserved != other.reserved:
            return False
        return True

    def __ne__(self, other):
        return not self.__eq__(other)
