const serviceWorkerExists = 'serviceWorker' in navigator && 'PushManager' in window;
let registrationPromise: Promise<ServiceWorkerRegistration> | null;

export function registerCallback(callback: (this: ServiceWorkerContainer, ev: MessageEvent) => any) {
    if (serviceWorkerExists) {
        (async () => {
            registrationPromise = navigator.serviceWorker.register('/ServiceWorker.js', { scope: '/' });
            navigator.serviceWorker.addEventListener('message', callback);
        })();
    }
}

function urlBase64ToUint8Array(base64String: string) {
    const padding = '='.repeat((4 - base64String.length % 4) % 4);
    const base64 = (base64String + padding)
        .replace(/-/g, '+')
        .replace(/_/g, '/');

    const rawData = window.atob(base64);
    const outputArray = new Uint8Array(rawData.length);

    for (let i = 0; i < rawData.length; ++i) {
        outputArray[i] = rawData.charCodeAt(i);
    }
    return outputArray;
}

export async function getPushRegistrationJSON(): Promise<any> {
    if (!serviceWorkerExists || !registrationPromise) {
        throw new Error('service worker not supported');
    }
    const registration = await registrationPromise;
    let subscription = await registration.pushManager.getSubscription();
    if (!subscription) {
        const subscribeOptions = {
            userVisibleOnly: true, //TODO: chrome does not allow false here, but it should be!
            applicationServerKey: urlBase64ToUint8Array(
                'BP62v95jRlEXxPlR3EbZ3hTgxpiLXmr-1_jGvLt3z8BKmLRcbSZideBoqEVqWLcs4oPDVn-nvhif659-vNHqk6A'
            )
        };
        subscription = await registration.pushManager.subscribe(subscribeOptions);
    }
    return subscription.toJSON();
}

export async function sendPushNotification(pushRegistration: string, message: string) {
    const res = await fetch('/push', {
        method: 'POST',
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json'
        }, body: JSON.stringify({ subscription: pushRegistration, message })
    });
    if (res.status === 410) {
        throw new Error('Invalid Registration');
    }
    if (res.status !== 200) {
        throw new Error(`Error sending push notification:${res.status} ${await res.text()}`);
    }
}