"""
Updates IRR objects in RIPE for the CCCamp IX.

This, given a mntner password and a list of ASNs taking part in the IXP will
ensure the right IRR objects are present:

 - an aut-num containing import/export RPSL rules
 - an as-set containing all member ASs.


"""

import difflib
import string
import sys
import time

import grpc
import requests

from bgpwtf.cccampix.proto import ix_pb2 as ipb
from bgpwtf.cccampix.proto import ix_pb2_grpc as ipb_grpc


class IRRObject:
    """An IRR object from RIPE."""
    TYPE = None
    def __init__(self, fields=None):
        self.fields = fields or []

    def add(self, k, v):
        self.fields.append((k, v))

    def render(self):
        """Render to IRR format."""
        return '\n'.join('{:16s}{}'.format(k+":", v) for k, v in self.fields) + "\n"

    @classmethod
    def from_ripe(cls, v):
        """Download this object from the RIPE REST API."""
        if cls.TYPE is None:
            raise Exception('cannot fetch untyped IRRObject')

        r = requests.get('https://rest.db.ripe.net/ripe/{}/{}.json'.format(cls.TYPE, v))
        d = r.json()

        obj = d['objects']['object'][0]
        assert obj['type'] == cls.TYPE
        assert obj['primary-key']['attribute'][0]['value'] == v

        attrs = obj['attributes']['attribute']

        fields = []
        for attr in attrs:
            # Skip metadata.
            if attr['name'] in ('created', 'last-modified'):
                continue
            fields.append((attr['name'], attr['value']))

        return cls(fields)

    def send_to_ripe(self, password):
        """Update this object (or create new) in RIPE using the SyncUpdates API."""
        res = self.render()
        res += 'password:       {}\n'.format(password)

        data = {
            'DATA': res,
        }
        r = requests.post('http://syncupdates.db.ripe.net/', files=data)
        res = r.text
        if 'Modify SUCCEEDED' not in res:
            print(res)
            raise Exception("Unexpected result from RIPE syncupdates")


banner = [
    ('remarks', r".--------------------------------------."),
    ('remarks', r"|   _                         _    __  |"),
    ('remarks', r"|  | |__   __ _ _ ____      _| |_ / _| |"),
    ('remarks', r"|  | '_ \ / _` | '_ \ \ /\ / / __| |_  |"),
    ('remarks', r"|  | |_) | (_| | |_) \ V  V /| |_|  _| |"),
    ('remarks', r"|  |_.__/ \__, | .__(_)_/\_/  \__|_|   |"),
    ('remarks', r"|         |___/|_|                     |"),
    ('remarks', r"|--------------------------------------|"),
    ('remarks', r"|  CCCamp2019 Internet Exchange Point  |"),
    ('remarks', r"'--------------------------------------'"),
    ('remarks', r''),
    ('remarks', r'// 21. - 25. August 2019'),
    ('remarks', r'// Ziegeleipark Mildenberg, Zehdenick, Germany, Earth, Milky Way'),
    ('remarks', r'// Join us: https://bgp.wtf/cccamp19'),
    ('remarks', r''),
]


class IXPAutNum(IRRObject):
    """An aut-num (AS) object."""
    TYPE = 'aut-num'
    @classmethod
    def make_for_members(cls, members):
        fields = [
            ('aut-num', 'AS208521'),
            ('as-name', 'BGPWTF-CCCAMP19-IX'),
        ] + banner + [
            ('remarks', '// Current members:'),
        ]

        for member in sorted(list(members)):
            fields.append(('import', 'from {} accept {}'.format(member, member)))
            fields.append(('export', 'to {} announce AS-CCCAMP19-IX'.format(member)))

        fields += [
            ('remarks', ''),
            ('remarks', '// Abuse: noc@hackerspace.pl'),
            ('org', 'ORG-SH103-RIPE'),
            ('admin-c', 'HACK2-RIPE'),
            ('tech-c', 'HACK2-RIPE'),
            ('status', 'ASSIGNED'),
            ('mnt-by', 'RIPE-NCC-END-MNT'),
            ('mnt-by', 'BGPWTF-AUTOMATION'),
            ('mnt-by', 'pl-hs-1-mnt'),
            ('source', 'RIPE'),
        ]

        return cls(fields)


class ASSet(IRRObject):
    """An as-set object."""
    TYPE = 'as-set'
    @classmethod
    def make_for_members(cls, members):
        fields = [
            ('as-set', 'AS-CCCAMP19-IX'),
            ('admin-c', 'HACK2-RIPE'),
        ] + banner + [
            ('remarks', '// Current members:'),
        ]

        for member in sorted(list(members)):
            fields.append(('members', member))

        fields += [
            ('remarks', ''),
            ('remarks', '// Abuse: noc@hackerspace.pl'),
            ('tech-c', 'HACK2-RIPE'),
            ('mnt-by', 'BGPWTF-AUTOMATION'),
            ('mnt-by', 'pl-hs-1-mnt'),
            ('source', 'RIPE'),
        ]

        return cls(fields)


def sync(want, got, password, force):
    """Sync an object if there is a diff to its current state."""
    wantr = want.render().split('\n')
    gotr = got.render().split('\n')

    d = list(difflib.unified_diff(gotr, wantr, fromfile='got', tofile='want'))
    fields_diff = set()
    for dd in d:
        if dd.startswith('---'):
            continue
        if dd.startswith('+++'):
            continue
        if not dd.startswith('+') and not dd.startswith('-'):
            continue

        field = dd[1:].split(':')[0]
        fields_diff.add(field)

    # We ignore remarks field changes, because the RIPE API returns us them always
    # mangled (with spaces missing in the ASCII art).
    if list(fields_diff) == ['remarks'] and not force:
        print('No changes.')
        return

    if force:
        print('Forcing update')
    else:
        print('Diff:')
        print('\n'.join(d))
    want.send_to_ripe(password)
    print('Updated.')


def sync_autnum(members, password, force=False):
    print('Syncing aut-num...')
    want = IXPAutNum.make_for_members(members)
    got = IXPAutNum.from_ripe('AS208521')
    sync(want, got, password, force)



def sync_asset(members, password, force=False):
    print('Syncing as-set...')
    want = ASSet.make_for_members(members)
    got = ASSet.from_ripe('AS-CCCAMP19-IX')
    sync(want, got, password, force)



if __name__ == '__main__':
    if len(sys.argv) != 3:
        print("Usage: {} <password> <verifier addr>".format(sys.argv[0]))
        sys.exit(1)

    password = sys.argv[1]
    verifier = sys.argv[2]

    chan = grpc.insecure_channel(verifier)
    stub = ipb_grpc.VerifierStub(chan)

    req = ipb.PeerSummaryRequest()
    peers = stub.PeerSummary(req)

    members = []
    for peer in peers:
        if peer.check_status != peer.STATUS_OK:
            continue
        members.append('AS'+str(peer.peeringdb_info.asn))

    print("Members:", members)
    sync_autnum(members, password)
    sync_asset(members, password)
