"""
login.py - Implement core login abstraction.
"""

from pylinkirc import conf, utils, world
from pylinkirc.log import log

try:
    from passlib.context import CryptContext
except ImportError:
    CryptContext = None
    log.warning("Hashed passwords are disabled because passlib is not installed. Please install "
                "it (pip3 install passlib) and restart for this feature to work.")

pwd_context = None
if CryptContext:
    pwd_context = CryptContext(["sha512_crypt", "sha256_crypt"],
                               sha256_crypt__default_rounds=180000,
                               sha512_crypt__default_rounds=90000)

def checkLogin(user, password):
    """Checks whether the given user and password is a valid combination."""
    accounts = conf.conf['login'].get('accounts')
    if not accounts:
        # No accounts specified, return.
        return False

    # Lowercase account names to make them case insensitive. TODO: check for
    # duplicates.
    user = user.lower()
    accounts = {k.lower(): v for k, v in accounts.items()}

    try:
        account = accounts[user]
    except KeyError:  # Invalid combination
        return False
    else:
        passhash = account.get('password')
        if not passhash:
            # No password given, return. XXX: we should allow plugins to override
            # this in the future.
            return False

        # Encryption in account passwords is optional (to not break backwards
        # compatibility).
        if account.get('encrypted', False):
            return verifyHash(password, passhash)
        else:
            return password == passhash

def verifyHash(password, passhash):
    """Checks whether the password given matches the hash."""
    if password:
        if not pwd_context:
            raise utils.NotAuthorizedError("Cannot log in to an account with a hashed password "
                                           "because passlib is not installed.")

        return pwd_context.verify(password, passhash)
    return False  # No password given!
