function dispatch(name) {
  // 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, name, "true");
  document.body.appendChild(form);
  form.submit();
}

async function attestation(options) {
  let credential;
  try {
    credential = await navigator.credentials.create({ "publicKey": options });
  }
  // cancel and timeout can occur besides error
  catch (error) {
    console.error(`Failed to create 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/attestation/result")
  addInput(form, "id", credential.id);
  addInput(form, "type", credential.type);
  addInput(form, "response.clientDataJSON", base64url.encode(credential.response.clientDataJSON));
  addInput(form, "response.attestationObject", base64url.encode(credential.response.attestationObject));
  document.body.appendChild(form);
  form.submit();
}

function startFido2() {

  if (!isWebAuthnSupportedByTheBrowser()) {
    dispatch("unsupported");
    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.user.id = base64url.decode(options.user.id);
    options.challenge = base64url.decode(options.challenge);
    if (options.excludeCredentials != null) {
      options.excludeCredentials = options.excludeCredentials.map((c) => {
        c.id = base64url.decode(c.id);
        return c;
      });
    }
    if (options.authenticatorSelection.authenticatorAttachment === null) {
      options.authenticatorSelection.authenticatorAttachment = undefined;
    }
    return attestation(options);
  }).catch((error) => {
    console.log('Error during FIDO2 onboarding: ' + error);
    dispatch("failed");
  });
}
