#! /usr/bin/env python3
"""
This is a prototypical implementation of a Zeek management client, as sketched
in the following architecture design doc:

https://docs.google.com/document/d/1r0wXnihx4yESOpLJ87Wh2g1V-aHOFUkbgiFe8RHJpZo/edit

Work on this client is currently in progress and maturing over the course of
the Zeek 4.x series. Feedback is welcome. This implementation adopts many of
the idioms and primitives also used by the zkg package manager.
"""
# https://pypi.org/project/argcomplete/#global-completion
# PYTHON_ARGCOMPLETE_OK

# Broker lessons learned:
#
# - When sending an event from Python results in an error message like the
#   following on the Zeek side ...
#
#     warning: failed to convert remote event '<some event type>' arg #<n>,
#         got vector, expected record
#
#   ... the reason is that some member of the structure in question (here,
#   a record) could not be unserialized properly.

import os.path
import sys

try:
    # Argcomplete provides command-line completion for users of argparse.
    # We support it if available, but don't complain when it isn't.
    import argcomplete  # pylint: disable=import-error
except ImportError:
    pass

# Prepend the Python path of the Zeek installation. This ensures we find the
# Zeek-bundled Broker Python bindings, if available, before any system-wide
# ones.
ZEEK_PYTHON_DIR = '/usr/local/lib/zeek/python'
if os.path.isdir(ZEEK_PYTHON_DIR):
    sys.path.insert(0, os.path.abspath(ZEEK_PYTHON_DIR))

import zeekclient  # pylint: disable=wrong-import-position


def main():
    # Preliminary configuration update: environment variables can already take
    # hold. This allows autocompleted settings to show values more accurately
    # than our hardwired defaults.
    zeekclient.CONFIG.update_from_env()

    parser = zeekclient.cli.create_parser()

    if 'argcomplete' in sys.modules:
        argcomplete.autocomplete(parser)

    args = parser.parse_args()

    # Finalize config settings in expected hierarchical order:
    zeekclient.CONFIG.update_from_file(args.configfile)
    zeekclient.CONFIG.update_from_env()
    zeekclient.CONFIG.update_from_args(args)

    if args.version:
        print(zeekclient.__version__)
        return 0

    # Establish logging as per requested verbosity and formatting
    if not args.quiet:
        zeekclient.logs.configure(
            zeekclient.CONFIG.getint('client', 'verbosity'),
            zeekclient.CONFIG.getboolean('client', 'rich_logging_format'))

    if not args.command:
        zeekclient.LOG.error('please provide a command to execute.')
        return 1

    try:
        return args.run_cmd(args)
    except KeyboardInterrupt:
        return 0


if __name__ == '__main__':
    sys.exit(main())
