"""__main__.py

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

from __future__ import annotations

import os
import sys
import argparse
from typing import cast

from exabgp.application import cli
from exabgp.application import run
from exabgp.application import server
from exabgp.application import decode
from exabgp.application import encode
from exabgp.application import environ
from exabgp.application import version
from exabgp.application import validate
from exabgp.application import healthcheck
from exabgp.application import shell
from exabgp.application import schema
from exabgp.application import export
from exabgp.application import example
from exabgp.application import migrate


def main() -> int | None:
    # Handle --env-file early, before Environment.setup() is called
    from exabgp.environment import base as envbase

    for i, arg in enumerate(sys.argv[1:], 1):
        if arg == '--env-file' and i < len(sys.argv) - 1:
            envbase.ENVFILE = sys.argv[i + 1]
            sys.argv = sys.argv[:i] + sys.argv[i + 2 :]
            break
        if arg.startswith('--env-file='):
            envbase.ENVFILE = arg.split('=', 1)[1]
            sys.argv = sys.argv[:i] + sys.argv[i + 1 :]
            break

    # Check if this is a CLI subprocess (pipe or socket)
    cli_mode = os.environ.get('exabgp_api_cli_mode', '')

    if cli_mode == 'pipe':
        cli_named_pipe = os.environ.get('exabgp_cli_pipe', '')
        if cli_named_pipe:
            from exabgp.application.pipe import main

            main(cli_named_pipe)
            sys.exit(0)
    elif cli_mode == 'socket':
        cli_unix_socket = os.environ.get('exabgp_cli_socket', '')
        if cli_unix_socket:
            from exabgp.application.unixsocket import main

            main(cli_unix_socket)
            sys.exit(0)

    # compatibility with exabgp 4.x
    if len(sys.argv) > 1 and not ('-h' in sys.argv or '--help' in sys.argv):
        if sys.argv[1] not in (
            'version',
            'cli',
            'run',
            'healthcheck',
            'decode',
            'encode',
            'configuration',
            'server',
            'env',
            'shell',
            'schema',
            'migrate',
        ):
            sys.argv = sys.argv[0:1] + ['server'] + sys.argv[1:]

    formatter = argparse.RawDescriptionHelpFormatter
    parser = argparse.ArgumentParser(
        description='The BGP swiss army knife of networking\n\n'
        'A configuration file can be passed directly:\n'
        '  exabgp config.conf     (equivalent to: exabgp server config.conf)\n\n'
        'Environment file override:\n'
        '  exabgp --env-file /path/to/exabgp.env server config.conf\n'
        '  EXABGP_ENVFILE=/path/to/exabgp.env exabgp server config.conf',
        formatter_class=formatter,
    )

    subparsers = parser.add_subparsers()

    sub = subparsers.add_parser('version', help='report exabgp version', description=version.__doc__)
    sub.set_defaults(func=version.cmdline)
    version.setargs(sub)

    sub = subparsers.add_parser(
        'cli',
        help='interactive CLI with tab completion',
        description='Interactive REPL mode with intelligent tab completion',
    )
    sub.set_defaults(
        func=lambda args: cli.cmdline_interactive(
            args.pipename if hasattr(args, 'pipename') else 'exabgp', 'exabgp', False, args
        )
    )
    sub.add_argument('--pipename', dest='pipename', metavar='NAME', help='Name of the pipe')
    sub.add_argument('--no-color', dest='no_color', action='store_true', help='Disable colored output')

    sub = subparsers.add_parser('run', help='execute single command (non-interactive)', description=run.__doc__)
    sub.set_defaults(func=run.cmdline)
    run.setargs(sub)

    sub = subparsers.add_parser(
        'healthcheck',
        help='monitor services and announce/withdraw routes',
        description=healthcheck.__doc__,
        formatter_class=formatter,
    )
    sub.set_defaults(func=healthcheck.cmdline)
    healthcheck.setargs(sub)

    sub = subparsers.add_parser('env', help='show exabgp configuration information', description=environ.__doc__)
    sub.set_defaults(func=environ.cmdline)
    environ.setargs(sub)

    sub = subparsers.add_parser('decode', help='decode hex-encoded bgp packets', description=decode.__doc__)
    sub.set_defaults(func=decode.cmdline)
    decode.setargs(sub)

    sub = subparsers.add_parser(
        'encode', help='encode route config to hex-encoded bgp packets', description=encode.__doc__
    )
    sub.set_defaults(func=encode.cmdline)
    encode.setargs(sub)

    sub = subparsers.add_parser('server', help='start exabgp', description=server.__doc__)
    sub.set_defaults(func=server.cmdline)
    server.setargs(sub)

    sub = subparsers.add_parser(
        'shell', help='manage shell completion', description='Install or uninstall shell completion scripts'
    )
    sub.set_defaults(func=shell.cmdline)
    shell.setargs(sub)

    sub = subparsers.add_parser('schema', help='export configuration schema', description=schema.__doc__)
    sub.set_defaults(func=schema.cmdline)
    schema.setargs(sub)

    # Configuration subcommand group
    config_parser = subparsers.add_parser(
        'configuration', help='configuration tools (validate, export)', description='Configuration management tools'
    )
    config_subparsers = config_parser.add_subparsers(dest='config_command')

    config_validate = config_subparsers.add_parser(
        'validate', help='validate configuration file', description=validate.__doc__
    )
    config_validate.set_defaults(func=validate.cmdline)
    validate.setargs(config_validate)

    config_export = config_subparsers.add_parser(
        'export', help='export parsed configuration to JSON', description=export.__doc__
    )
    config_export.set_defaults(func=export.cmdline)
    export.setargs(config_export)

    config_example = config_subparsers.add_parser(
        'example', help='generate documented configuration example', description=example.__doc__
    )
    config_example.set_defaults(func=example.cmdline)
    example.setargs(config_example)

    # Migration tools subcommand group
    migrate_parser = subparsers.add_parser(
        'migrate', help='migrate configuration/API between versions', description=migrate.__doc__
    )
    migrate_parser.set_defaults(func=migrate.cmdline)
    migrate.setargs(migrate_parser)

    try:
        cmdarg = parser.parse_args()
    except Exception as exc:
        sys.exit(exc.args[-1])

    options = vars(cmdarg)

    if 'func' in options:
        return cast(int | None, cmdarg.func(cmdarg))
    parser.print_help()
    environ.default()
    return 1


if __name__ == '__main__':
    try:
        code = main()
        sys.exit(code)
    except BrokenPipeError:
        # there was a PIPE ( ./sbin/exabgp | command )
        # and command does not work as should
        sys.exit(1)
