"""Commands for working with local profiles."""

__all__ = [
    "register",
]

import sys

from . import (
    colorized,
    Command,
    print_with_pager,
    PROFILE_DEFAULT,
    PROFILE_NAMES,
    read_input,
    TableCommand,
    tables,
)
from .. import (
    bones,
    utils,
)
from ..bones import helpers
from ..utils import (
    auth,
    profiles,
)
from ..utils.async import asynchronous


class cmd_login(Command):
    """Log-in to a MAAS with either username and password or apikey.

    The username and password will NOT be saved; a new API key will be
    obtained from MAAS and associated with the new profile. This key can be
    selectively revoked from the Web UI, for example, at a later date.
    """

    def __init__(self, parser):
        super(cmd_login, self).__init__(parser)
        parser.add_argument(
            "-p", "--profile-name", default=None, help=(
                "The name to give the profile. Default is the username used "
                "to login."))
        parser.add_argument(
            '--apikey', default=None, help=(
                "The API key acquired from MAAS. This requires the profile "
                "name to be provided as well."))
        parser.add_argument(
            '-k', '--insecure', action='store_true', help=(
                "Disable SSL certificate check"), default=False)
        parser.add_argument(
            "url", nargs="?", type=utils.api_url, help=(
                "The URL of the API, e.g. http://example.com/MAAS/ "
                "or http://example.com/MAAS/api/2.0/ if you wish to specify "
                "the API version. If no URL is provided then it will be "
                "prompted for, interactively."))
        parser.add_argument(
            "username", nargs="?", default=None, help=(
                "The username used to login to MAAS. If no username is "
                "provided and API key is not being used it will be prompted "
                "for, interactively."))
        parser.add_argument(
            "password", nargs="?", default=None, help=(
                "The password used to login to MAAS. If no password is "
                "proviced and API key is not being used it will be promoed "
                "for, interactively."))

    @asynchronous
    async def __call__(self, options):
        if options.apikey and not options.profile_name:
            raise ValueError(
                "-p,--profile-name must be provided with --apikey")
        if not options.url:
            url = read_input("URL", validator=utils.api_url)
        else:
            url = options.url
        if not options.apikey:
            if not options.username:
                username = read_input("Username")
            else:
                username = options.username
            if not options.password:
                password = read_input("Password", password=True)
            else:
                password = options.password
                if password == '-':
                    password = sys.stdin.readline().strip()
            profile = await helpers.login(
                url, username=username, password=password,
                insecure=options.insecure)
        else:
            credentials = auth.obtain_credentials(options.apikey)
            session = await bones.SessionAPI.fromURL(
                url, credentials=credentials, insecure=options.insecure)
            profile = profiles.Profile(
                options.profile_name, url, credentials=credentials,
                description=session.description)

        if options.profile_name:
            profile = profile.replace(name=options.profile_name)

        # Save a new profile.
        with profiles.ProfileStore.open() as config:
            config.save(profile)
            config.default = profile

        self.print_whats_next(profile)

    @staticmethod
    def print_whats_next(profile):
        """Explain what to do next."""
        what_next = [
            "{{autogreen}}Congratulations!{{/autogreen}} You are logged in "
            "to the MAAS server at {{autoblue}}{profile.url}{{/autoblue}} "
            "with the profile name {{autoblue}}{profile.name}{{/autoblue}}.",
            "For help with the available commands, try:",
            "  maas help",
            ]
        for message in what_next:
            message = message.format(profile=profile)
            print(colorized(message))
            print()


class cmd_logout(Command):
    """Logout of a MAAS profile, purging any stored credentials.

    This will remove the given profile from your command-line client. You can
    re-create it later using `add` or `login`.
    """

    def __init__(self, parser):
        super(cmd_logout, self).__init__(parser)
        parser.add_argument(
            "profile_name", metavar="profile-name",
            nargs="?", choices=PROFILE_NAMES, help=(
                "The profile name you want to logout of." +
                ("" if PROFILE_DEFAULT is None else " [default: %(default)s]")
            ),
        )
        if PROFILE_DEFAULT is not None:
            parser.set_defaults(profile_name=PROFILE_DEFAULT.name)

    def __call__(self, options):
        with profiles.ProfileStore.open() as config:
            config.delete(options.profile_name)


class cmd_switch(Command):
    """Switch the active profile.

    This will switch the currently active profile to the given profile. The
    previous profile will remain, just use `switch` again to go back.
    """

    def __init__(self, parser):
        super(cmd_switch, self).__init__(parser)
        parser.add_argument(
            "profile_name", metavar="profile-name", choices=PROFILE_NAMES,
            help=(
                "The profile name you want to switch to."
            ),
        )

    def __call__(self, options):
        with profiles.ProfileStore.open() as config:
            profile = config.load(options.profile_name)
            config.default = profile


class cmd_profiles(TableCommand):
    """List profiles (aka. logged in MAAS's)."""

    def __init__(self, parser):
        super(cmd_profiles, self).__init__(parser)
        parser.add_argument(
            "--refresh", action='store_true', default=False, help=(
                "Retrieves the latest version of the help information for "
                "all profiles. Use it to update your command-line client's "
                "information after an upgrade to the MAAS server."),
        )
        parser.other.add_argument(
            "--no-pager", action='store_true',
            help=(
                "Don't use the pager when printing the output of the "
                "command."))

    def __call__(self, options):
        if options.refresh:
            with profiles.ProfileStore.open() as config:
                for profile_name in config:
                    profile = config.load(profile_name)
                    session = bones.SessionAPI.fromProfile(profile)
                    profile = profile.replace(description=session.description)
                    config.save(profile)
        else:
            table = tables.ProfilesTable()
            with profiles.ProfileStore.open() as config:
                if options.no_pager:
                    print(table.render(options.format, config))
                else:
                    print_with_pager(table.render(options.format, config))


def register(parser):
    """Register profile commands with the given parser."""
    cmd_login.register(parser)
    cmd_logout.register(parser)
    cmd_switch.register(parser)
    cmd_profiles.register(parser)
