#!/usr/bin/python3
#
# Copyright (c) 2019 AT&T Intellectual Property.
# All rights reserved.
#
# SPDX-License-Identifier: GPL-2.0-only
#

""" This is run to get the CGNAT public information from the dataplane
and provide it as YANG RPC information. """


import os
import sys
import getopt
import vplaned
import json
from vyatta.npf.npf_debug import NpfDebug


PROGNAME = os.path.basename(__file__)
DATAPLANE_CMD = 'cgn-op show apm'

# class used for printing debugs
dbg = NpfDebug()


def err(msg):
    print(msg, file=sys.stderr)


def process_options():
    try:
        opts, args = getopt.getopt(sys.argv[1:], "d", ['debug'])

    except getopt.GetoptError as r:
        err(r)
        err("usage: {} [-d|--debug] ".format(sys.argv[0]))
        sys.exit(2)

    for opt, arg in opts:
        if opt in ('-d', '--debug'):
            dbg.enable()


def pub_rpc(entry):
    rpc_entry = {}
    rpc_entry['public-address'] = entry['address']
    rpc_entry['start-port'] = entry['port_start']
    rpc_entry['end-port'] = entry['port_end']
    rpc_entry['total-port-blocks'] = entry['nblocks']
    rpc_entry['active-port-blocks'] = entry['blocks_used']

    dbg.pprint("rpc entry: {}".format(rpc_entry))

    return rpc_entry


param_mappings = {
    'ip-address-prefix': 'address',
    'start-index': 'start',
    'max-entries': 'count',
}


def get_cgnat_public_info():
    dbg.pprint("get_cgnat_public_info()")

    try:
        rpc_input = json.load(sys.stdin)
    except ValueError as exc:
        err("Failed to parse input JSON: {}".format(exc))
        return None, 1

    args = DATAPLANE_CMD
    start = None
    count = None

    for param, value in rpc_input.items():
        dp_param = param_mappings.get(param)
        if dp_param is None:
            err("{}: unknown rpc input option: {}".format(PROGNAME, param))
            return None, 2

        if dp_param == 'start':
            start = value
        elif dp_param == 'count':
            count = value
        else:
            args += " {} {}".format(dp_param, value)

    # dataplane requires a start if given a count
    if count is not None and start is None:
        start = "1"

    if start is not None:
        args += " start {}".format(start)

    if count is not None:
        args += " count {}".format(count)

    dbg.pprint("dp command: {}".format(args))

    pub_info_list = []
    with vplaned.Controller() as controller:
        for dp in controller.get_dataplanes():
            with dp:
                dp_dict = dp.json_command(args)
                if dp_dict and dp_dict.get('apm'):
                    dbg.pprint("dataplane dict: {}".format(
                        dp_dict['apm']))
                    for pub_addr in dp_dict['apm']:
                        pub_info_list.append(pub_rpc(pub_addr))

    if pub_info_list:
        return {'public-addresses': pub_info_list}, 0
    else:
        return None, 0


if __name__ == "__main__":
    process_options()
    info, ret = get_cgnat_public_info()
    if info:
        print(json.dumps(info))
    exit(ret)
