import socket

from django.utils.translation import ugettext as _
from djblets.util.humanize import humanize_list


class SSHError(Exception):
    """An SSH-related error."""
    pass


class MakeSSHDirError(IOError, SSHError):
    def __init__(self, dirname):
        IOError.__init__(_("Unable to create directory %(dirname)s, which is "
                           "needed for the SSH host keys. Create this "
                           "directory, set the web server's user as the "
                           "the owner, and make it writable only by that "
                           "user.") % {
            'dirname': dirname,
        })


class SSHAuthenticationError(SSHError):
    """An error representing a failed authentication over SSH.

    This takes a list of SSH authentication types that are allowed.
    Primarily, we respond to "password" and "publickey".

    This may also take the user's SSH key that was tried, if any.
    """
    def __init__(self, allowed_types=[], msg=None, user_key=None):
        if allowed_types:
            msg = _('Unable to authenticate against this repository using one '
                    'of the supported authentication types '
                    '(%(allowed_types)s).') % {
                'allowed_types': humanize_list(allowed_types),
            }
        elif not msg:
            msg = _('Unable to authenticate against this repository using one '
                    'of the supported authentication types.')

        SSHError.__init__(self, msg)
        self.allowed_types = allowed_types
        self.user_key = user_key


class UnsupportedSSHKeyError(SSHError):
    """An error representing an unsupported type of SSH key."""
    def __init__(self):
        SSHError.__init__(self,
                          _('This SSH key is not a valid RSA or DSS key.'))


class SSHKeyError(SSHError):
    """An error involving a host key on an SSH connection."""
    def __init__(self, hostname, key, message):
        from reviewboard.ssh.utils import humanize_key

        SSHError.__init__(self, message)
        self.hostname = hostname
        self.key = humanize_key(key)
        self.raw_key = key


class BadHostKeyError(SSHKeyError):
    """An error representing a bad or malicious key for an SSH connection."""
    def __init__(self, hostname, key, expected_key):
        from reviewboard.ssh.utils import humanize_key

        SSHKeyError.__init__(
            self, hostname, key,
            _("Warning! The host key for server %(hostname)s does not match "
              "the expected key.\n"
              "It's possible that someone is performing a man-in-the-middle "
              "attack. It's also possible that the RSA host key has just "
              "been changed. Please contact your system administrator if "
              "you're not sure. Do not accept this host key unless you're "
              "certain it's safe!")
            % {
                'hostname': hostname,
                'ip_address': socket.gethostbyname(hostname),
            })
        self.expected_key = humanize_key(expected_key)
        self.raw_expected_key = expected_key


class UnknownHostKeyError(SSHKeyError):
    """An error representing an unknown host key for an SSH connection."""
    def __init__(self, hostname, key):
        SSHKeyError.__init__(
            self, hostname, key,
            _("The authenticity of the host '%(hostname)s (%(ip)s)' "
              "couldn't be determined.") % {
                'hostname': hostname,
                'ip': socket.gethostbyname(hostname),
            }
        )
