#! /usr/bin/python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2014, 2015 Cumulus Networks, Inc. All rights reserved.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc.
# 51 Franklin Street, Fifth Floor
# Boston, MA  02110-1301, USA.
""" Control program for managing vxsnd.
"""
import json
import operator
import sys

from docopt import DocoptExit


def main():
    """
    Usage:
        vxsndctl -h
        vxsndctl [-u UDS_FILE] [-j] fdb [debug]
        vxsndctl [-u UDS_FILE] [-j] fdb [<vni>] [debug]
        vxsndctl [-u UDS_FILE] [-j] fdb (add <vni> <ip> | del <vni> <ip> |
                                         file <filename>)
        vxsndctl [-u UDS_FILE] [-j] get config [<parameter>]
        vxsndctl [-u UDS_FILE] [-j] set config <parameter> [<value>]
        vxsndctl [-u UDS_FILE] [-j] set debug (on | off)
        vxsndctl [-u UDS_FILE] [-j] show [detail]

    Options:
        -h, --help   : Show this screen and exit
        -u UDS_FILE  : File name for Unix domain socket
                       [default: /var/run/vxsnd.sock]
        -j           : Print result as json string

    Commands:
        fdb: print the vxsnd forwarding DB
        fdb <vni>: print the vxsnd forwarding DB for a vni
        get config: print the vxsnd configuration
        get config <parameter>: print single vxsnd config option
        set config <parameter> [<value>]: set a single vxsnd config option
        set debug on: enable debug mode and set loglevel to debug
        set debug off: disable debug mode and set loglevel to previous level
        show: print a snapshot of the runtime configuration
        show detail: print a detailed snapshot of the runtime configuration
    """
    from docopt import docopt
    from vxfld.common import mgmt

    args = docopt(main.__doc__, argv=sys.argv[1:] or ['-h'])
    mgmt_client = mgmt.MgmtClient(args['-u'])
    resp, err = mgmt_client.sendobj(args)
    if err:
        raise Exception('Error return: "%s"' % err)
    if resp is None:
        return 0
    if args['-j'] and not args['config']:
        print json.dumps(resp)
    elif args['fdb']:
        # This was a fdb request
        if args['debug']:
            fmt = '{:<8}    {:<12}    {:<6}    {:<12}'
            print fmt.format('VNI', 'Address', 'Ageout', 'NodeId')
            print fmt.format('===', '=======', '======', '======')
            for vni in sorted(resp.keys()):
                for ip_addr, holdtime, identifier in \
                        sorted(resp[vni], key=operator.itemgetter(0)):
                    print fmt.format(vni, ip_addr, holdtime, identifier)
        else:
            fmt = '{:<8}    {:<12}    {:<6}'
            print fmt.format('VNI', 'Address', 'Ageout')
            print fmt.format('===', '=======', '======')
            for vni in sorted(resp.keys()):
                for ip_addr, holdtime, _ in set(resp[vni]):
                    print fmt.format(vni, ip_addr, holdtime)
    elif args['get'] and args['config']:
        print json.dumps(resp, sort_keys=True, indent=4,
                         separators=(',', ': '))
    elif args['set'] and args['config']:
        print json.dumps(resp, sort_keys=True, indent=4,
                         separators=(',', ': '))
    elif args['show']:
        print 'Protocol version: %s' % resp['version']
        fmt = '{:<15}    {:<15}    {:<40}'
        addr_per_line = 2
        print fmt.format('Local address', 'Anycast address', 'Peer Addresses')
        print fmt.format('=============', '===============', '==============')
        if resp:
            peer_addresses = sorted(resp['peers'])
            for idx in range(0, max(len(peer_addresses), 1), addr_per_line):
                peer_addr_str = ', '.join(
                    peer_addresses[idx:idx+addr_per_line])
                if idx == 0:
                    print fmt.format(resp['local'], resp['anycast'],
                                     peer_addr_str)
                else:
                    print fmt.format('', '', peer_addr_str)
            if args['detail']:
                fmt = '{:<34}    {:<30}'
                print
                print fmt.format('Data (UDP) Port', 'Control (UDP) Port')
                print fmt.format('==============', '=================')
                print fmt.format(resp['data_port'], resp['ctrl_port'])
        else:
            print 'None'
    else:
        print '%r' % resp
    return 0

if __name__ == '__main__':
    try:
        sys.exit(main())
    except DocoptExit as ex:
        print ex
    except (KeyboardInterrupt, SystemExit):
        pass
    except Exception as ex:  # pylint: disable=broad-except
        sys.stderr.write('%s\n' % ex)
        sys.exit(1)
