import argparse
from typing import List

from fugue.lib import Interface


def _add_arguments_new(sp: argparse.Namespace) -> None:
    """
    # fugue interface new -h
    """
    # required
    sp.add_argument(
        "--private_key",
        type=str,
        required=True,
        dest="private_key",
        help="Interface private_key",
    )
    sp.add_argument(
        "--address",
        type=str,
        required=True,
        dest="address",
        help="Interface address",
    )
    sp.add_argument(
        "--listen_port",
        type=str,
        required=True,
        dest="listen_port",
        help="Interface listen_port",
    )

    # optional
    sp.add_argument(
        "--name", type=str, required=False, dest="name", help="Interface name"
    )
    sp.add_argument(
        "--dns",
        type=str,
        action="append",
        required=False,
        dest="dns",
        help="Interface dns",
    )
    sp.add_argument(
        "--table",
        type=str,
        required=False,
        dest="table",
        help="Interface table",
    )
    sp.add_argument(
        "--mtu", type=str, required=False, dest="mtu", help="Interface mtu"
    )
    sp.add_argument(
        "--pre_up",
        type=str,
        action="append",
        required=False,
        dest="pre_ups",
        help="Interface pre_ups",
    )
    sp.add_argument(
        "--post_up",
        type=str,
        action="append",
        required=False,
        dest="post_ups",
        help="Interface post_ups",
    )
    sp.add_argument(
        "--pre_down",
        type=str,
        action="append",
        dest="pre_downs",
        required=False,
        help="Interface pre_downs",
    )
    sp.add_argument(
        "--post_down",
        type=str,
        action="append",
        required=False,
        dest="post_downs",
        help="Interface post_downs",
    )


def _add_arguments_set(
    sp: argparse.Namespace, init_interfaces: List[Interface]
) -> None:
    """
    # fugue interface set -h
    """
    # required
    sp.add_argument(
        "-n",
        "--name",
        type=str,
        required=True,
        choices=[interface.name for interface in init_interfaces],
        dest="name",
        help="Interface name",
    )

    # optional
    sp.add_argument(
        "--private_key",
        type=str,
        required=False,
        default=None,
        dest="private_key",
        help="Interface private_key",
    )
    sp.add_argument(
        "--address",
        type=str,
        required=False,
        default=None,
        dest="address",
        help="Interface address",
    )
    sp.add_argument(
        "--listen_port",
        type=str,
        required=False,
        default=None,
        dest="listen_port",
        help="Interface listen_port",
    )
    sp.add_argument(
        "--name",
        type=str,
        required=False,
        default=None,
        dest="name",
        help="Interface name",
    )
    sp.add_argument(
        "--dns",
        type=str,
        action="append",
        required=False,
        default=None,
        dest="dns",
        help="Interface dns",
    )
    sp.add_argument(
        "--table",
        type=str,
        required=False,
        default=None,
        dest="table",
        help="Interface table",
    )
    sp.add_argument(
        "--mtu",
        type=str,
        required=False,
        default=None,
        dest="mtu",
        help="Interface mtu",
    )
    sp.add_argument(
        "--pre_up",
        type=str,
        action="append",
        required=False,
        default=None,
        dest="pre_ups",
        help="Interface pre_ups",
    )
    sp.add_argument(
        "--post_up",
        type=str,
        action="append",
        required=False,
        default=None,
        dest="post_ups",
        help="Interface post_ups",
    )
    sp.add_argument(
        "--pre_down",
        type=str,
        action="append",
        dest="pre_downs",
        default=None,
        required=False,
        help="Interface pre_downs",
    )
    sp.add_argument(
        "--post_down",
        type=str,
        action="append",
        required=False,
        default=None,
        dest="post_downs",
        help="Interface post_downs",
    )


def _add_arguments_rm(
    sp: argparse.Namespace, init_interfaces: List[Interface]
) -> None:
    """
    # fugue interface rm -h
    """
    # required
    sp.add_argument(
        "-n",
        "--name",
        type=str,
        required=True,
        choices=[interface.name for interface in init_interfaces],
        dest="name",
        help="Interface name",
    )


def check_args(args: argparse.Namespace) -> None:
    if args.command == "interface":
        if args.action == "set":
            # check at least one was provided (https://stackoverflow.com/a/6723066)
            if not (
                args.private_key
                or args.address
                or args.listen_port
                or args.name
                or args.dns
                or args.table
                or args.mtu
                or args.pre_ups
                or args.post_ups
                or args.pre_downs
                or args.post_downs
            ):
                raise RuntimeError(
                    "error: in interface set command, at least one option must be provided"
                )


def set_subparser(
    subparsers: argparse.Namespace, init_interfaces: List[Interface]
) -> argparse.Namespace:
    subparser_interface = subparsers.add_parser(
        "interface", help="interface commands."
    )

    # the subparser had subparsers
    subparser_interface_subparsers = subparser_interface.add_subparsers(
        help="interface actions", dest="action"
    )

    subparser_interface_new = subparser_interface_subparsers.add_parser(
        "new", help="Create new interface."
    )
    _ = subparser_interface_subparsers.add_parser(
        "show", help="Show existing interfaces."
    )
    subparser_interface_rm = subparser_interface_subparsers.add_parser(
        "rm", help="Remove interface."
    )

    _add_arguments_new(subparser_interface_new)
    # add_argument_show(subparser_interface_new)
    _add_arguments_rm(subparser_interface_rm, init_interfaces)

    return subparser_interface
