import json, base64
from functools import lru_cache

import cryptography.hazmat.backends
from cryptography import x509
import jwt

try:
    from botocore.vendored import requests
except ImportError:
    import requests

class FIDOMetadataClient:
    mds_url = "https://mds.fidoalliance.org/"
    _metadata_toc = None

    @property
    def metadata_toc(self):
        if self._metadata_toc is None:
            res = requests.get(self.mds_url)
            res.raise_for_status()
            jwt_header = jwt.get_unverified_header(res.content)
            assert jwt_header["alg"] == "ES256"
            cert = x509.load_der_x509_certificate(jwt_header["x5c"][0].encode(),
                                                  cryptography.hazmat.backends.default_backend())
            self._metadata_toc = jwt.decode(res.content, key=cert.public_key(), algorithms=["ES256"])
        return self._metadata_toc

    @lru_cache(64)
    def metadata_for_key_id(self, key_id):
        for e in self.metadata_toc["entries"]:
            if key_id in e.get("attestationCertificateKeyIdentifiers", []):
                break
        else:
            raise KeyError("No metadata found for key ID {}".format(key_id))
        res = requests.get(e["url"])
        res.raise_for_status()
        return json.loads(base64.b64decode(res.content).decode())