## _args.py
# Common argument parsing code.
import argparse
import functools
import logging
import pydle


def client_from_args(name, description, default_nick="Bot", cls=pydle.Client):
    # Parse some arguments.
    parser = argparse.ArgumentParser(
        name,
        description=description,
        add_help=False,
        epilog="This program is part of {package}.".format(package=pydle.__name__),
    )

    meta = parser.add_argument_group("Meta")
    meta.add_argument(
        "-h", "--help", action="help", help="What you are reading right now."
    )
    meta.add_argument(
        "-v",
        "--version",
        action="version",
        version="{package}/%(prog)s {ver}".format(
            package=pydle.__name__, ver=pydle.__version__
        ),
        help="Dump version number.",
    )
    meta.add_argument(
        "-V",
        "--verbose",
        help="Be verbose in warnings and errors.",
        action="store_true",
        default=False,
    )
    meta.add_argument(
        "-d", "--debug", help="Show debug output.", action="store_true", default=False
    )

    conn = parser.add_argument_group("Connection")
    conn.add_argument("server", help="The server to connect to.", metavar="SERVER")
    conn.add_argument(
        "-p", "--port", help="The port to use. (default: 6667, 6697 (TLS))"
    )
    conn.add_argument("-P", "--password", help="Server password.", metavar="PASS")
    conn.add_argument(
        "--tls", help="Use TLS. (default: no)", action="store_true", default=False
    )
    conn.add_argument(
        "--verify-tls",
        help="Verify TLS certificate sent by server. (default: no)",
        action="store_true",
        default=False,
    )
    conn.add_argument(
        "-e",
        "--encoding",
        help="Connection encoding. (default: UTF-8)",
        default="utf-8",
        metavar="ENCODING",
    )

    init = parser.add_argument_group("Initialization")
    init.add_argument(
        "-n",
        "--nickname",
        help="Nickname. Can be set multiple times to set fallback nicknames. (default: {})".format(
            default_nick
        ),
        action="append",
        dest="nicknames",
        default=[],
        metavar="NICK",
    )
    init.add_argument(
        "-u",
        "--username",
        help="Username. (default: derived from nickname)",
        metavar="USER",
    )
    init.add_argument(
        "-r",
        "--realname",
        help="Realname (GECOS). (default: derived from nickname)",
        metavar="REAL",
    )
    init.add_argument(
        "-c",
        "--channel",
        help="Channel to automatically join. Can be set multiple times for multiple channels.",
        action="append",
        dest="channels",
        default=[],
        metavar="CHANNEL",
    )

    auth = parser.add_argument_group("Authentication")
    auth.add_argument(
        "--sasl-identity",
        help="Identity to use for SASL authentication. (default: <empty>)",
        default="",
        metavar="SASLIDENT",
    )
    auth.add_argument(
        "--sasl-username",
        help="Username to use for SASL authentication.",
        metavar="SASLUSER",
    )
    auth.add_argument(
        "--sasl-password",
        help="Password to use for SASL authentication.",
        metavar="SASLPASS",
    )
    auth.add_argument(
        "--sasl-mechanism",
        help="Mechanism to use for SASL authentication.",
        metavar="SASLMECH",
    )
    auth.add_argument(
        "--tls-client-cert", help="TLS client certificate to use.", metavar="CERT"
    )
    auth.add_argument(
        "--tls-client-cert-keyfile",
        help="Keyfile to use for TLS client cert.",
        metavar="KEYFILE",
    )

    args = parser.parse_args()

    # Set nicknames straight.
    if not args.nicknames:
        nick = default_nick
        fallback = []
    else:
        nick = args.nicknames.pop(0)
        fallback = args.nicknames

    # Set log level.
    if args.debug:
        log_level = logging.DEBUG
    elif not args.verbose:
        log_level = logging.ERROR

    logging.basicConfig(level=log_level)

    # Setup client and connect.
    client = cls(
        nickname=nick,
        fallback_nicknames=fallback,
        username=args.username,
        realname=args.realname,
        sasl_identity=args.sasl_identity,
        sasl_username=args.sasl_username,
        sasl_password=args.sasl_password,
        sasl_mechanism=args.sasl_mechanism,
        tls_client_cert=args.tls_client_cert,
        tls_client_cert_key=args.tls_client_cert_keyfile,
    )

    connect = functools.partial(
        client.connect,
        hostname=args.server,
        port=args.port,
        password=args.password,
        encoding=args.encoding,
        channels=args.channels,
        tls=args.tls,
        tls_verify=args.verify_tls,
    )

    return client, connect
