"""
GnuPG abstraction layer

Copyright (C) 2010-2020 Cr@ns <roots@crans.org>
Authors : Daniel Stan <daniel.stan@crans.org>
          Vincent Le Gallic <legallic@crans.org>
          Alexandre Iooss <erdnaxe@crans.org>
SPDX-License-Identifier: GPL-3.0-or-later
"""

import subprocess
import logging

import gpg

# Local logger
log = logging.getLogger(__name__)


def decrypt(ciphertext: str):
    """
    Return decrypted content
    """
    log.info("Decrypting using GnuPG")
    with gpg.Context() as c:
        plaintext, _, _ = c.decrypt(ciphertext.encode("utf-8"))
    return plaintext.decode("utf-8")


def encrypt(content: str, keys: []) -> str:
    """
    Return encrypted content for keys
    """
    log.info("Encrypting using GnuPG")
    with gpg.Context() as c:
        c.armor = True
        cipher, _, _ = c.encrypt(content.encode("utf-8"), keys)
    return cipher.decode("utf-8")


def receive_key(fpr: str):
    """
    Download key from fingerprint
    """
    full_command = ['gpg', '--recv-keys', fpr]
    log.info("Running `%s`" % " ".join(full_command))
    return subprocess.run(full_command)


def check_key_validity(key, email: str) -> bool:
    """
    Check key identities email and trust level
    Return true if can be trusted
    """
    log.info("Checking %s key with email %s" % (key.fpr, email))
    for uid in key.uids:
        if email == uid.email and not uid.revoked and not uid.invalid \
                and uid.validity >= gpg.constants.validity.FULL:
            return True

    # no trusted valid uid were found
    return False


def get_key(fpr):
    """
    Get GnuPG key by fingerprint, ask to download if missing
    """
    # TODO: use --force and ignore-invalid
    log.info("Getting key corresponding to %s" % fpr)
    with gpg.Context() as c:
        try:
            return c.get_key(fpr)
        except gpg.errors.KeyNotFound:
            log.error("key correponding to fingerprint %s not found" % fpr)

            # ask to download key
            answer = input("Do you want to try to import it now ? [Y/n] ")
            if answer.lower() == "y" or answer == "":
                receive_key(fpr)
                return get_key(fpr)