import { fromByteArray } from 'base64-js';

// Show an error in the U2F login page
function showU2FError(error) {
}

// Encode an ArrayBuffer into a base64 string.
function bufferEncode(value) {
    return fromByteArray(value)
        .replace(/\+/g, "-")
        .replace(/\//g, "_")
        .replace(/=/g, "");
}

function bufferDecode(value) {
    return Uint8Array.from(atob(value.replace(/-/g, '+').replace(/_/g, '/')), c => c.charCodeAt(0));
}

function verifyAssertion(url, assertedCredential) {
    // Move data into Arrays incase it is super long
    console.log('calling verify')
    let authData = new Uint8Array(assertedCredential.response.authenticatorData);
    let clientDataJSON = new Uint8Array(assertedCredential.response.clientDataJSON);
    let rawId = new Uint8Array(assertedCredential.rawId);
    let sig = new Uint8Array(assertedCredential.response.signature);
    let userHandle = new Uint8Array(assertedCredential.response.userHandle);

    document.getElementById('webauthnFormField').value = JSON.stringify({
            id: assertedCredential.id,
            rawId: bufferEncode(rawId),
            type: assertedCredential.type,
            response: {
                authenticatorData: bufferEncode(authData),
                clientDataJSON: bufferEncode(clientDataJSON),
                signature: bufferEncode(sig),
                userHandle: bufferEncode(userHandle),
            },
    });
    document.getElementById('webauthnForm').submit();
}

function logoutService(el, service_name, logout_url) {
    console.log('logging out of ' + service_name);

    fetch(logout_url, {
        method: 'GET',
        credentials: 'include',
    })
        .then(response => {
            el.classList.add('logout-status-ok');
            el.innerHTML = 'OK';
            console.log('successful logout for ' + service_name);
        })
        .catch(err => {
            el.classList.add('logout-status-error');
            el.innerHTML = 'ERROR';
            console.log('error logging out of ' + service_name);
        });
}

document.addEventListener("DOMContentLoaded", function() {

    // Activate WebAuthN login process if the WebAuthN data element is found.
    var webauthnEl = document.getElementById('webAuthNData');
    if (webauthnEl) {
        var validationURL = webauthnEl.dataset.webauthnUrl;
        var makeAssertionOptions = JSON.parse(webauthnEl.dataset.webauthnCredentialAssertion);

        console.log('webauthn validation url: ' + validationURL);
        console.log('webauthn assertion options:');
        console.log(makeAssertionOptions);

        // Decode key material and turn into uint8 arrays.
        makeAssertionOptions.publicKey.challenge = bufferDecode(makeAssertionOptions.publicKey.challenge);
        makeAssertionOptions.publicKey.allowCredentials.forEach(function (listItem) {
            listItem.id = bufferDecode(listItem.id)
        });

        navigator.credentials.get({
            publicKey: makeAssertionOptions.publicKey
        })
            .then(function(credential) {
                console.log('credential:');
                console.log(credential);

                // Decode the clientDataJSON into a utf-8 string.
                const utf8Decoder = new TextDecoder('utf-8');
                const decodedClientData = utf8Decoder.decode(
                    credential.response.clientDataJSON);

                // parse the string as an object
                const clientDataObj = JSON.parse(decodedClientData);

                console.log(clientDataObj);

                verifyAssertion(validationURL, credential);
            })
            .catch((error) => {
                // Show the error to the user. Drop the reference to the
                // RFC, if present, as that's just confusing to the user.
                var msg = error.message.replace(/\..*$/, '.');
                document.getElementById('u2fError').innerText = msg;
                console.log('WebAuthN ERROR: ' + msg);
            });
    }

    // Activate the logout process if logout elements are found in the document.
    document.querySelectorAll('.service-logout').forEach(el => {
        var url = el.dataset.serviceLogoutUrl;
        var name = el.dataset.serviceName;
        logoutService(el, name, url);
    });

});