<script type="text/javascript">

    "use strict";

    const service_worker = '/js/notifications/service-worker.js';

    function urlBase64ToUint8Array(base64String) {

        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;
    }

    /**** START register-sw ****/
    function registerServiceWorker() {

        return navigator.serviceWorker
                        .register(service_worker)
                        .then(function (registration) {

                            registration.update();

                            console.log('Service worker successfully registered.');

                            return registration;
                        })
                        .catch(function (err) {

                            console.log('Unable to register service worker.');
                            console.log(err);
                        });
    }

    /**** END register-sw ****/

// This is just to make sample code eaier to read.
// TODO: Move into a variable rather than register each time.
    function getSWRegistration() {

        return navigator.serviceWorker.register(service_worker);
    }

    /**** START request-permission ****/
    function askPermission() {

        return new Promise(function (resolve, reject) {

            const permissionResult = Notification.requestPermission(function (result) {

                resolve(result);
            });

            if (permissionResult) {

                permissionResult.then(resolve, reject);
            }
        }).then(function (permissionResult) {

            if (permissionResult !== 'granted') {

                throw new Error('We weren\'t granted permission.');
            }
        });
    }

    /**** END request-permission ****/

    /**
     * Using `Notification.permission` directly can be slow (locks on the main
     * thread). Using the permission API with a fallback to
     * `Notification.permission` is preferable.
     * @return {Promise<String>} Returns a promise that resolves to a notification
     * permission state string.
     */
    /**** START get-permission-state ****/
    function getNotificationPermissionState() {

        if (navigator.permissions) {

            return navigator.permissions
                            .query({name: 'notifications'})
                            .then(function (result) {

                                return result.state;
                            });
        }

        return new Promise(function (result) {

            resolve(Notification.permission);
        });
    }

    /**** START send-subscription-to-server ****/
    function sendSubscriptionToBackEnd(subscription) {

        return fetch('/push-notification', {
            method     : 'POST',
            headers    : new Headers({
                                         'Content-Type': 'application/json;',
                                         'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
                                     }),
            credentials: 'include',
            body       : JSON.stringify(subscription)
        }).then(function (response) {

            console.log('Push Notifications Controller Response.').console.log(response);

            if (!response.ok) {

                throw new Error('Bad status code from server.');
            }

            return response.json();
        }).then(function (responseData) {

            if (!(responseData.data && responseData.data.success)) {

                throw new Error('Bad response from server.');
            }
        });
    }

    /**** END send-subscription-to-server ****/

    /**** START subscribe-user ****/
    function subscribeUserToPush() {

        return getSWRegistration()
            .then(function (registration) {

                const subscribeOptions = {
                    userVisibleOnly     : true,
                    applicationServerKey: urlBase64ToUint8Array("{{ env('VAPID_PUBLIC_KEY') }}")
                };

                return registration.pushManager.subscribe(subscribeOptions);
            })
            .then(function (pushSubscription) {

                console.log('Received PushSubscription: ', JSON.stringify(pushSubscription));

                return pushSubscription;
            });
    }

    /**** END subscribe-user ****/

    function setUpPush() {

        return Promise.all([
                               registerServiceWorker(),
                               getNotificationPermissionState()
                           ])
                      .then(function (results) {

                          const currentPermissionState = results[1];

                          if (currentPermissionState === 'denied') {

                              console.warn('The notification permission has been blocked. Nothing we can do.');

                              return;
                          }

                          let promiseChain = Promise.resolve();

                          if (currentPermissionState !== 'granted') {

                              promiseChain = askPermission();
                          }

                          promiseChain.then(subscribeUserToPush).then(function (subscription) {

                              if (subscription) {

                                  return sendSubscriptionToBackEnd(subscription).then(function () {
                                      return subscription;
                                  });
                              }

                              return subscription;
                          }).catch(function (err) {

                              console.log('Failed to subscribe the user.');
                              console.log(err);
                          });
                      }).catch(function (err) {

                console.error('Unable to register the service worker.', err);
            });
    }

    /*window.onload = function () {

     /!**** START feature-detect ****!/
     if (!('serviceWorker' in navigator)) {

     // Service Worker isn't supported on this browser, disable or hide UI.
     return;
     }

     if (!('PushManager' in window)) {

     // Push isn't supported on this browser, disable or hide UI.
     return;
     }
     /!**** END feature-detect ****!/

     // Push is supported.
     setUpPush();
     };*/
</script>