let baseURL; // base URL
let statusToken; // used to check progress
let dispatcherElement; // to display link or QR code
let infoElement; // to display info text
let errorElement; // to display error text

function addInput(form, name, value) {
  const input = document.createElement("input");
  input.name = name;
  input.value = value;
  form.appendChild(input);
}

function submitStatus(status) {
  // we have to do a form POST instead of AJAX
  const form = document.createElement("form");
  form.method = "POST";
  form.style.display = "none";
  addInput(form, "status", status);
  document.body.appendChild(form);
  form.submit();
}

const Status = {
    _pollInterval: 2 * 1000, // Check every 2 seconds
    latest: null,

    startPolling: function (token, uiCallback) {
        let interval = setInterval(async () => {
            await this._check(token).then(function (resp) {
                console.log("Polling status: %o", resp);
                uiCallback && uiCallback(resp, false);
                return Status.latest = resp;
            })
            .catch(function (err) {
                console.error("Error during polling: %o", err);
                return false;
            });
            if (Status.latest && (Status.latest.status === 'succeeded' || Status.latest.status === 'failed' || Status.latest.status === 'unknown')) {
                // Done!
                console.log('Latest status is: %o', this.latest);
                uiCallback && uiCallback(this.latest, true);
                clearInterval(interval);
            }
        }, this._pollInterval);
    },

    _check: async function (token) {
        const payload = { statusToken: token };
        const response = await fetch(baseURL + 'api/v1/status', {
            method: 'POST',
            mode: 'cors',
            cache: 'no-cache',
            credentials: 'omit',
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json;charset=utf-8'
            },
            body: JSON.stringify(payload),
            redirect: 'follow',
            referrerPolicy: 'no-referrer'
        });

        return await response.json();
    }
};

function setDeepLinkLabel(button) {
    const text = document.getElementsByName('info.deeplink')[0].value;
    button.innerHTML = text;
}

function messageScanQR() {
    const text = document.getElementsByName('info.qrcode')[0].value;
    infoElement.innerHTML = text;
}

function messageInstalledAccessApp() {
  const text = document.getElementById('info.access_app.installed').innerText;
  infoElement.innerHTML = text;
}

const AccessAppElement = {

    _elem: null, // QR code or deep link depending on device

    show: function (appLink) {
        const userAgent = navigator.userAgent || navigator.vendor || window.opera;
        const isIphone = 'iPhone' === navigator.platform;
        const isAndroid = /android/i.test(userAgent) && /mobile/i.test(userAgent);
        if (isAndroid || isIphone) {
            if (isAndroid) {
                document.getElementById('install_apple').style.display = 'none';
            }
            if (isIphone) {
                document.getElementById('install_google').style.display = 'none';
            }
            this._elem = document.createElement('a');
            this._elem.setAttribute('href', appLink);
            this._elem.setAttribute('class', 'btn btn-primary w-100');
            this._elem.setAttribute('target', '_blank');
            // distinguishes style for platforms
            dispatcherElement.classList.add('mobile-platform');
            const accessApplinks = document.getElementById('access-app-download-link');
            accessApplinks.classList.add('access-app-download-link-mobile-spacing');

            dispatcherElement.appendChild(this._elem);
            setDeepLinkLabel(this._elem);

            // info text is displayed before access app links
            accessApplinks.parentNode.insertBefore(infoElement.parentNode, accessApplinks);
            messageInstalledAccessApp();
        }
        else {
            messageScanQR();
            const qrSize = 280;
            // Element to render the QR code
            this._elem = document.createElement('canvas');
            // Wrapper div to render corners
            const qrCodeWrapper = document.createElement('div');
            qrCodeWrapper.setAttribute('id','qr-code-wrapper');
            qrCodeWrapper.style.width = `${qrSize}px`;
            qrCodeWrapper.style.height = `${qrSize}px`;
            qrCodeWrapper.appendChild(this._elem)
            dispatcherElement.style.height = `${qrSize}px`;
            dispatcherElement.appendChild(qrCodeWrapper);
            const qrcode = new QRious({
              element: this._elem,
              // use --nevis-gray-900 CSS variable value
              foreground: getComputedStyle(document.body).getPropertyValue('--nevis-gray-900'),
              level: "M",
              size: qrSize,
              value: appLink
            });
        }
    },

    hide: function() {
        // hide the element which was shown
        if (this._elem != null) {
            this._elem.style.display = "none";
        }
    }
};

function onboardUser(appLink) {

    AccessAppElement.show(appLink);

    console.log('Starting Auth Cloud status polling...');

    Status.startPolling(statusToken, (st, done) => {

        if (st.status === 'succeeded') {

            console.log('Auth Cloud success.');

            // auto submit form with outcome
            submitStatus('succeeded')
        }
        else if (st.status === 'failed') {

            // failed: The transaction failed, either by timeout or because the user did not accept.
            console.warn('Authentication Cloud onboarding failed. User abort or timeout.');

            submitStatus('failed')
        }
        else if (st.status === 'unknown') {

            console.error('Authentication Cloud onboarding failed. Unknown status.');

            submitStatus('unknown')
        }
    });
}

const swap = function (nodeA, nodeB) {
    const parentA = nodeA.parentNode;
    const siblingA = nodeA.nextSibling === nodeB ? nodeA : nodeA.nextSibling;

    // Move `nodeA` to before the `nodeB`
    nodeB.parentNode.insertBefore(nodeA, nodeB);

    // Move `nodeB` to before the sibling of `nodeA`
    parentA.insertBefore(nodeB, siblingA);
};

function init() {

    const form = document.getElementById('authcloud_onboard');

    baseURL = form.url.value;
    statusToken = form.statusToken.value;

    infoElement = document.getElementById('authcloud_info');
    errorElement = document.getElementById('authcloud_error');

    dispatcherElement = document.getElementById('authcloud_dispatch');

    // info texts are displayed underneath QR code
    swap(infoElement.parentNode, dispatcherElement.parentNode);

    const appLink = form.appLink.value;
    onboardUser(appLink);
}

window.onload = function() {
  init();
};
