from boltons.fileutils import AtomicSaver
from cryptography.hazmat.primitives import serialization
from cryptography import x509
from typing import TYPE_CHECKING, Union

if TYPE_CHECKING:
    from cryptography.hazmat.primitives.asymmetric.types import CertificateIssuerPrivateKeyTypes
    from cryptography.hazmat.primitives.asymmetric.types import PrivateKeyTypes

CERTIFICATE_TYPES = Union[x509.Certificate, x509.CertificateSigningRequest]


# ---------------------------------------------------------------------------
def save_private_key(
    key: Union['CertificateIssuerPrivateKeyTypes', 'PrivateKeyTypes'],
    path: str,
) -> Union['CertificateIssuerPrivateKeyTypes', 'PrivateKeyTypes']:
    """
    Save a Private key to the specified path
    """
    with AtomicSaver(path) as f:
        f.write(
            key.private_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PrivateFormat.TraditionalOpenSSL,
                encryption_algorithm=serialization.NoEncryption(),
            )
        )

    return key


# ---------------------------------------------------------------------------
def save_x509_pem(pem: CERTIFICATE_TYPES, path: str) -> CERTIFICATE_TYPES:
    """
    Save the x509 Certificate or Certificate Signing Request to the specified path.
    """
    with AtomicSaver(path) as f:
        f.write(pem.public_bytes(serialization.Encoding.PEM))

    return pem


# ---------------------------------------------------------------------------
def value_to_hex(i: Union[int, str]) -> str:
    """Create a hex-representation of the given value.

    >>> value_to_hex(645812291030797929864531914362914497264204243776)
    '711F39857EE9CDA390D845795CDBABF2629DE340'
    """
    try:
        return hex(int(i))[2:].upper()
    except (TypeError, ValueError):
        return str(i)


__all__ = (
    'save_private_key',
    'save_x509_pem',
    'value_to_hex',
)
