# -*- coding: utf-8 -*-

# # If nacl/encryption is optional.  Also, the checks in functions would probably
# # then be best as a wrapper.
# try:
#     import nacl.utils
#     import nacl.public
#     NACL_AVAILABLE = True

# except ImportError:
#     print(
#         'Importing car.encrypt, but note that the functions in this module '
#         'require  PyNaCl, which appears not to be available.')
#     NACL_AVAILABLE = False


def generate_nacl_keypair():
    """
    Returns two objects, (a nacl.public.PublicKey, a nacl.public.PrivateKey)
    for encryption using nacl.public.Box or nacl.public.SealedBox.
    (We'll use SealedBox in this code, since we provide code signing
    separately.)
    """
    # if not NACL_AVAILABLE:
    #     # TODO: Consider a dependency error class.
    #     raise Exception('encrypt() requires PyNaCl, which is not available.')

    private = nacl.public.PrivateKey.generate()
    public = private.public_key

    return private, public


def raw_key_from_nacl_key(nacl_key):
    """
    Given an nacl.public.PrivateKey or an nacl.public.PublicKey, returns the
    underlying 32-byte key value (a Curve25519 key).
    """
    if not (isinstance(nacl_key, nacl.public.PublicKey)
            or isinstance(nacl_key, nacl.public.PrivateKey)):
        raise TypeError('Expecting a PublicKey or PrivateKey object')
    return nacl_key.encode()


def private_nacl_key_from_raw_key(key_value):
    """
    Given a raw key value (32 bytes, a Curve25519 key), generates an
    nacl.public.PrivateKey object using that key value, which can then be used
    for encryption and decryption via the PyNaCl library (nacl.public).
    """
    # ✅ TODO: Argument validation (bytes, Python2 & Python3)
    nacl.public.PrivateKey(key_value)


def public_nacl_key_from_raw_key(key_value):
    """
    Given a raw key value (32 bytes, a Curve25519 key), generates an
    nacl.public.PublicKey object using that key value, which can then be used
    for encryption via the PyNaCl library (nacl.public).
    """
    # ✅ TODO: Argument validation (bytes, Python2 & Python3)
    nacl.public.PublicKey(key_value)



def encrypt(data, public_key):
    """
    Takes bytes and a public key (nacl.public.PublicKey), returns encrypted
    data (bytes) that can be decrypted using the corresponding private key.
    """
    # if not NACL_AVAILABLE:
    #     # TODO: Consider a dependency error class.
    #     raise Exception('encrypt() requires PyNaCl, which is not available.')

    if not isinstance(public_key, nacl.public.PublicKey):
        raise TypeError('Arg "public_key" must be a nacl.public.PublicKey.')

    encryptor = nacl.public.SealedBox(public_key)

    return encryptor.encrypt(data)



def decrypt(encrypted, private_key):
    """
    Takes bytes and a private key (nacl.public.PrivateKey), returns decrypted
    data (bytes).
    """
    # if not NACL_AVAILABLE:
    #     # TODO: Consider a dependency error class.
    #     raise Exception('decrypt() requires PyNaCl, which is not available.')

    if not isinstance(private_key, nacl.public.PrivateKey):
        raise TypeError('Arg "private_key" must be a nacl.public.PrivateKey.')

    decryptor = nacl.public.SealedBox(private_key)

    return decryptor.decrypt(encrypted)
