(function() {
  'use strict'

  async function assertion(options) {
    let credential;
    try {
      credential = await navigator.credentials.get({ "publicKey": options });
    }
    // Cancel and timeout can occur besides error
    catch (error) {
      console.error(`Failed to get WebAuthn credential: ${error}`);
      throw error;
    }
    // as this is the last call we have to do a top-level request instead of AJAX
    const form = document.createElement("form");
    form.method = "POST";
    form.style.display = "none";
    addInput(form, "path", "/nevisfido/fido2/assertion/result")
    addInput(form, "id", credential.id);
    addInput(form, "type", credential.type);
    addInput(form, "response.clientDataJSON", base64url.encode(credential.response.clientDataJSON));
    addInput(form, "response.authenticatorData", base64url.encode(credential.response.authenticatorData));
    addInput(form, "response.signature", base64url.encode(credential.response.signature));
    document.body.appendChild(form);
    form.submit();
  }

  function authenticate() {
    // WebAuthn feature detection
    if (!isWebAuthnSupportedByTheBrowser()) {
      cancelFido2();
      return;
    };

    const request = {};
    request.path = "/nevisfido/fido2/attestation/options";

    // calling nevisFIDO through nevisAuth on current URL using AJAX
    fetch("", {
      method: "POST",
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(request)
    })
    .then(res => res.json())
    .then(options => {
      options.challenge = base64url.decode(options.challenge);
      options.allowCredentials = options.allowCredentials.map((c) => {
        c.id = base64url.decode(c.id);
        return c;
      });
      return assertion(options);
    }).catch((error) => {
      console.error(`Error during FIDO2 authentication: ${error}`);
      cancelFido2();
    });
  }

  authenticate();
})();
