/**
 * Push v1.0
 * https://github.com/Nickersoft/push.js
 * =========
 * A compact, cross-browser solution for the JavaScript Notifications API
 *
 * Credits
 * -------
 * Tsvetan Tsvetkov (ttsvetko)
 * Alex Gibson (alexgibson)
 *
 * License
 * -------
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2015-2017 Tyler Nickerson
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
(function (global, factory) {
	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
	typeof define === 'function' && define.amd ? define(factory) :
	(global.Push = factory());
}(this, (function () { 'use strict';

function _typeof(obj) {
  if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
    _typeof = function (obj) {
      return typeof obj;
    };
  } else {
    _typeof = function (obj) {
      return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
    };
  }

  return _typeof(obj);
}

function _classCallCheck(instance, Constructor) {
  if (!(instance instanceof Constructor)) {
    throw new TypeError("Cannot call a class as a function");
  }
}

function _defineProperties(target, props) {
  for (var i = 0; i < props.length; i++) {
    var descriptor = props[i];
    descriptor.enumerable = descriptor.enumerable || false;
    descriptor.configurable = true;
    if ("value" in descriptor) descriptor.writable = true;
    Object.defineProperty(target, descriptor.key, descriptor);
  }
}

function _createClass(Constructor, protoProps, staticProps) {
  if (protoProps) _defineProperties(Constructor.prototype, protoProps);
  if (staticProps) _defineProperties(Constructor, staticProps);
  return Constructor;
}

function _inherits(subClass, superClass) {
  if (typeof superClass !== "function" && superClass !== null) {
    throw new TypeError("Super expression must either be null or a function");
  }

  subClass.prototype = Object.create(superClass && superClass.prototype, {
    constructor: {
      value: subClass,
      enumerable: false,
      writable: true,
      configurable: true
    }
  });
  if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}

function _possibleConstructorReturn(self, call) {
  if (call && (typeof call === "object" || typeof call === "function")) {
    return call;
  }

  if (self === void 0) {
    throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
  }

  return self;
}

var errorPrefix = 'PushError:';
var Messages = {
  errors: {
    incompatible: "".concat(errorPrefix, " Push.js is incompatible with browser."),
    invalid_plugin: "".concat(errorPrefix, " plugin class missing from plugin manifest (invalid plugin). Please check the documentation."),
    invalid_title: "".concat(errorPrefix, " title of notification must be a string"),
    permission_denied: "".concat(errorPrefix, " permission request declined"),
    sw_notification_error: "".concat(errorPrefix, " could not show a ServiceWorker notification due to the following reason: "),
    sw_registration_error: "".concat(errorPrefix, " could not register the ServiceWorker due to the following reason: "),
    unknown_interface: "".concat(errorPrefix, " unable to create notification: unknown interface")
  }
};

var Permission =
/*#__PURE__*/
function () {
  // Private members
  // Public members
  function Permission(win) {
    _classCallCheck(this, Permission);
    this._win = win;
    this.GRANTED = 'granted';
    this.DEFAULT = 'default';
    this.DENIED = 'denied';
    this._permissions = [this.GRANTED, this.DEFAULT, this.DENIED];
  }
  /**
  * Requests permission for desktop notifications
  * @param {Function} onGranted - Function to execute once permission is granted
  * @param {Function} onDenied - Function to execute once permission is denied
  * @return {void, Promise}
  */


  _createClass(Permission, [{
    key: "request",
    value: function request(onGranted, onDenied) {
      return arguments.length > 0 ? this._requestWithCallback.apply(this, arguments) : this._requestAsPromise();
    }
    /**
    * Old permissions implementation deprecated in favor of a promise based one
    * @deprecated Since V1.0.4
    * @param {Function} onGranted - Function to execute once permission is granted
    * @param {Function} onDenied - Function to execute once permission is denied
    * @return {void}
    */

  }, {
    key: "_requestWithCallback",
    value: function _requestWithCallback(onGranted, onDenied) {
      var _this = this;

      var existing = this.get();

      var resolve = function resolve() {
        var result = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _this._win.Notification.permission;
        if (typeof result === 'undefined' && _this._win.webkitNotifications) result = _this._win.webkitNotifications.checkPermission();

        if (result === _this.GRANTED || result === 0) {
          if (onGranted) onGranted();
        } else if (onDenied) onDenied();
      };
      /* Permissions already set */


      if (existing !== this.DEFAULT) {
        resolve(existing);
      } else if (this._win.webkitNotifications && this._win.webkitNotifications.checkPermission) {
        /* Safari 6+, Legacy webkit browsers */
        this._win.webkitNotifications.requestPermission(resolve);
      } else if (this._win.Notification && this._win.Notification.requestPermission) {
        /* Chrome 23+ */
        this._win.Notification.requestPermission().then(resolve).catch(function () {
          if (onDenied) onDenied();
        });
      } else if (onGranted) {
        /* Let the user continue by default */
        onGranted();
      }
    }
    /**
    * Requests permission for desktop notifications in a promise based way
    * @return {Promise}
    */

  }, {
    key: "_requestAsPromise",
    value: function _requestAsPromise() {
      var _this2 = this;

      var existing = this.get();

      var isGranted = function isGranted(result) {
        return result === _this2.GRANTED || result === 0;
      };
      /* Permissions already set */


      var hasPermissions = existing !== this.DEFAULT;
      /* Safari 6+, Chrome 23+ */

      var isModernAPI = this._win.Notification && this._win.Notification.requestPermission;
      /* Legacy webkit browsers */

      var isWebkitAPI = this._win.webkitNotifications && this._win.webkitNotifications.checkPermission;
      return new Promise(function (resolvePromise, rejectPromise) {
        var resolver = function resolver(result) {
          return isGranted(result) ? resolvePromise() : rejectPromise();
        };

        if (hasPermissions) {
          resolver(existing);
        } else if (isWebkitAPI) {
          _this2._win.webkitNotifications.requestPermission(function (result) {
            resolver(result);
          });
        } else if (isModernAPI) {
          _this2._win.Notification.requestPermission().then(function (result) {
            resolver(result);
          }).catch(rejectPromise);
        } else resolvePromise();
      });
    }
    /**
    * Returns whether Push has been granted permission to run
    * @return {Boolean}
    */

  }, {
    key: "has",
    value: function has() {
      return this.get() === this.GRANTED;
    }
    /**
    * Gets the permission level
    * @return {Permission} The permission level
    */

  }, {
    key: "get",
    value: function get() {
      var permission;
      /* Safari 6+, Chrome 23+ */

      if (this._win.Notification && this._win.Notification.permission) permission = this._win.Notification.permission;else if (this._win.webkitNotifications && this._win.webkitNotifications.checkPermission)
        /* Legacy webkit browsers */
        permission = this._permissions[this._win.webkitNotifications.checkPermission()];else if (navigator.mozNotification)
        /* Firefox Mobile */
        permission = this.GRANTED;else if (this._win.external && this._win.external.msIsSiteMode)
        /* IE9+ */
        permission = this._win.external.msIsSiteMode() ? this.GRANTED : this.DEFAULT;else permission = this.GRANTED;
      return permission;
    }
  }]);
  return Permission;
}();

var Util =
/*#__PURE__*/
function () {
  function Util() {
    _classCallCheck(this, Util);
  }

  _createClass(Util, null, [{
    key: "isUndefined",
    value: function isUndefined(obj) {
      return obj === undefined;
    }
  }, {
    key: "isNull",
    value: function isNull(obs) {
      return obj === null;
    }
  }, {
    key: "isString",
    value: function isString(obj) {
      return typeof obj === 'string';
    }
  }, {
    key: "isFunction",
    value: function isFunction(obj) {
      return obj && {}.toString.call(obj) === '[object Function]';
    }
  }, {
    key: "isObject",
    value: function isObject(obj) {
      return _typeof(obj) === 'object';
    }
  }, {
    key: "objectMerge",
    value: function objectMerge(target, source) {
      for (var key in source) {
        if (target.hasOwnProperty(key) && this.isObject(target[key]) && this.isObject(source[key])) {
          this.objectMerge(target[key], source[key]);
        } else {
          target[key] = source[key];
        }
      }
    }
  }]);
  return Util;
}();

var AbstractAgent = function AbstractAgent(win) {
  _classCallCheck(this, AbstractAgent);
  this._win = win;
};

/**
 * Notification agent for modern desktop browsers:
 * Safari 6+, Firefox 22+, Chrome 22+, Opera 25+
 */
var DesktopAgent$$1 =
/*#__PURE__*/
function (_AbstractAgent) {
  _inherits(DesktopAgent$$1, _AbstractAgent);

  function DesktopAgent$$1() {
    _classCallCheck(this, DesktopAgent$$1);
    return _possibleConstructorReturn(this, (DesktopAgent$$1.__proto__ || Object.getPrototypeOf(DesktopAgent$$1)).apply(this, arguments));
  }

  _createClass(DesktopAgent$$1, [{
    key: "isSupported",

    /**
     * Returns a boolean denoting support
     * @returns {Boolean} boolean denoting whether webkit notifications are supported
     */
    value: function isSupported() {
      return this._win.Notification !== undefined;
    }
    /**
     * Creates a new notification
     * @param title - notification title
     * @param options - notification options array
     * @returns {Notification}
     */

  }, {
    key: "create",
    value: function create(title, options) {
      return new this._win.Notification(title, {
        icon: Util.isString(options.icon) || Util.isUndefined(options.icon) || Util.isNull(options.icon) ? options.icon : options.icon.x32,
        body: options.body,
        tag: options.tag,
        requireInteraction: options.requireInteraction
      });
    }
    /**
     * Close a given notification
     * @param notification - notification to close
     */

  }, {
    key: "close",
    value: function close(notification) {
      notification.close();
    }
  }]);
  return DesktopAgent$$1;
}(AbstractAgent);

/**
 * Notification agent for modern desktop browsers:
 * Safari 6+, Firefox 22+, Chrome 22+, Opera 25+
 */
var MobileChromeAgent$$1 =
/*#__PURE__*/
function (_AbstractAgent) {
  _inherits(MobileChromeAgent$$1, _AbstractAgent);

  function MobileChromeAgent$$1() {
    _classCallCheck(this, MobileChromeAgent$$1);
    return _possibleConstructorReturn(this, (MobileChromeAgent$$1.__proto__ || Object.getPrototypeOf(MobileChromeAgent$$1)).apply(this, arguments));
  }

  _createClass(MobileChromeAgent$$1, [{
    key: "isSupported",

    /**
     * Returns a boolean denoting support
     * @returns {Boolean} boolean denoting whether webkit notifications are supported
     */
    value: function isSupported() {
      return this._win.navigator !== undefined && this._win.navigator.serviceWorker !== undefined;
    }
    /**
     * Returns the function body as a string
     * @param func
     */

  }, {
    key: "getFunctionBody",
    value: function getFunctionBody(func) {
      var str = func.toString().match(/function[^{]+{([\s\S]*)}$/);
      return typeof str !== 'undefined' && str !== null && str.length > 1 ? str[1] : null;
    }
    /**
     * Creates a new notification
     * @param id                ID of notification
     * @param title             Title of notification
     * @param options           Options object
     * @param serviceWorker     ServiceWorker path
     * @param callback          Callback function
     */

  }, {
    key: "create",
    value: function create(id, title, options, serviceWorker, callback) {
      var _this = this;

      /* Register ServiceWorker */
      this._win.navigator.serviceWorker.register(serviceWorker);

      this._win.navigator.serviceWorker.ready.then(function (registration) {
        /* Local data the service worker will use */
        var localData = {
          id: id,
          link: options.link,
          origin: document.location.href,
          onClick: Util.isFunction(options.onClick) ? _this.getFunctionBody(options.onClick) : '',
          onClose: Util.isFunction(options.onClose) ? _this.getFunctionBody(options.onClose) : ''
        };
        /* Merge the local data with user-provided data */

        if (options.data !== undefined && options.data !== null) localData = Object.assign(localData, options.data);
        /* Show the notification */

        registration.showNotification(title, {
          icon: options.icon,
          body: options.body,
          vibrate: options.vibrate,
          tag: options.tag,
          data: localData,
          requireInteraction: options.requireInteraction,
          silent: options.silent
        }).then(function () {
          registration.getNotifications().then(function (notifications) {
            /* Send an empty message so the ServiceWorker knows who the client is */
            registration.active.postMessage('');
            /* Trigger callback */

            callback(notifications);
          });
        }).catch(function (error) {
          throw new Error(Messages.errors.sw_notification_error + error.message);
        });
      }).catch(function (error) {
        throw new Error(Messages.errors.sw_registration_error + error.message);
      });
    }
    /**
     * Close all notification
     */

  }, {
    key: "close",
    value: function close() {// Can't do this with service workers
    }
  }]);
  return MobileChromeAgent$$1;
}(AbstractAgent);

/**
 * Notification agent for modern desktop browsers:
 * Safari 6+, Firefox 22+, Chrome 22+, Opera 25+
 */
var MobileFirefoxAgent$$1 =
/*#__PURE__*/
function (_AbstractAgent) {
  _inherits(MobileFirefoxAgent$$1, _AbstractAgent);

  function MobileFirefoxAgent$$1() {
    _classCallCheck(this, MobileFirefoxAgent$$1);
    return _possibleConstructorReturn(this, (MobileFirefoxAgent$$1.__proto__ || Object.getPrototypeOf(MobileFirefoxAgent$$1)).apply(this, arguments));
  }

  _createClass(MobileFirefoxAgent$$1, [{
    key: "isSupported",

    /**
     * Returns a boolean denoting support
     * @returns {Boolean} boolean denoting whether webkit notifications are supported
     */
    value: function isSupported() {
      return this._win.navigator.mozNotification !== undefined;
    }
    /**
     * Creates a new notification
     * @param title - notification title
     * @param options - notification options array
     * @returns {Notification}
     */

  }, {
    key: "create",
    value: function create(title, options) {
      var notification = this._win.navigator.mozNotification.createNotification(title, options.body, options.icon);

      notification.show();
      return notification;
    }
  }]);
  return MobileFirefoxAgent$$1;
}(AbstractAgent);

/**
 * Notification agent for IE9
 */
var MSAgent$$1 =
/*#__PURE__*/
function (_AbstractAgent) {
  _inherits(MSAgent$$1, _AbstractAgent);

  function MSAgent$$1() {
    _classCallCheck(this, MSAgent$$1);
    return _possibleConstructorReturn(this, (MSAgent$$1.__proto__ || Object.getPrototypeOf(MSAgent$$1)).apply(this, arguments));
  }

  _createClass(MSAgent$$1, [{
    key: "isSupported",

    /**
     * Returns a boolean denoting support
     * @returns {Boolean} boolean denoting whether webkit notifications are supported
     */
    value: function isSupported() {
      return this._win.external !== undefined && this._win.external.msIsSiteMode !== undefined;
    }
    /**
     * Creates a new notification
     * @param title - notification title
     * @param options - notification options array
     * @returns {Notification}
     */

  }, {
    key: "create",
    value: function create(title, options) {
      /* Clear any previous notifications */
      this._win.external.msSiteModeClearIconOverlay();

      this._win.external.msSiteModeSetIconOverlay(Util.isString(options.icon) || Util.isUndefined(options.icon) ? options.icon : options.icon.x16, title);

      this._win.external.msSiteModeActivate();

      return null;
    }
    /**
     * Close a given notification
     * @param notification - notification to close
     */

  }, {
    key: "close",
    value: function close() {
      this._win.external.msSiteModeClearIconOverlay();
    }
  }]);
  return MSAgent$$1;
}(AbstractAgent);

/**
 * Notification agent for old Chrome versions (and some) Firefox
 */
var WebKitAgent$$1 =
/*#__PURE__*/
function (_AbstractAgent) {
  _inherits(WebKitAgent$$1, _AbstractAgent);

  function WebKitAgent$$1() {
    _classCallCheck(this, WebKitAgent$$1);
    return _possibleConstructorReturn(this, (WebKitAgent$$1.__proto__ || Object.getPrototypeOf(WebKitAgent$$1)).apply(this, arguments));
  }

  _createClass(WebKitAgent$$1, [{
    key: "isSupported",

    /**
     * Returns a boolean denoting support
     * @returns {Boolean} boolean denoting whether webkit notifications are supported
     */
    value: function isSupported() {
      return this._win.webkitNotifications !== undefined;
    }
    /**
     * Creates a new notification
     * @param title - notification title
     * @param options - notification options array
     * @returns {Notification}
     */

  }, {
    key: "create",
    value: function create(title, options) {
      var notification = this._win.webkitNotifications.createNotification(options.icon, title, options.body);

      notification.show();
      return notification;
    }
    /**
     * Close a given notification
     * @param notification - notification to close
     */

  }, {
    key: "close",
    value: function close(notification) {
      notification.cancel();
    }
  }]);
  return WebKitAgent$$1;
}(AbstractAgent);

var Push$$1 =
/*#__PURE__*/
function () {
  // Private members
  // Public members
  function Push$$1(win) {
    _classCallCheck(this, Push$$1);

    /* Private variables */

    /* ID to use for new notifications */
    this._currentId = 0;
    /* Map of open notifications */

    this._notifications = {};
    /* Window object */

    this._win = win;
    /* Public variables */

    this.Permission = new Permission(win);
    /* Agents */

    this._agents = {
      desktop: new DesktopAgent$$1(win),
      chrome: new MobileChromeAgent$$1(win),
      firefox: new MobileFirefoxAgent$$1(win),
      ms: new MSAgent$$1(win),
      webkit: new WebKitAgent$$1(win)
    };
    this._configuration = {
      serviceWorker: '/serviceWorker.min.js',
      fallback: function fallback(payload) {}
    };
  }
  /**
   * Closes a notification
   * @param id            ID of notification
   * @returns {boolean}   denotes whether the operation was successful
   * @private
   */


  _createClass(Push$$1, [{
    key: "_closeNotification",
    value: function _closeNotification(id) {
      var success = true;
      var notification = this._notifications[id];

      if (notification !== undefined) {
        success = this._removeNotification(id);
        /* Safari 6+, Firefox 22+, Chrome 22+, Opera 25+ */

        if (this._agents.desktop.isSupported()) this._agents.desktop.close(notification);else if (this._agents.webkit.isSupported())
          /* Legacy WebKit browsers */
          this._agents.webkit.close(notification);else if (this._agents.ms.isSupported())
          /* IE9 */
          this._agents.ms.close();else {
          success = false;
          throw new Error(Messages.errors.unknown_interface);
        }
        return success;
      }

      return false;
    }
    /**
    * Adds a notification to the global dictionary of notifications
    * @param {Notification} notification
    * @return {Integer} Dictionary key of the notification
    * @private
    */

  }, {
    key: "_addNotification",
    value: function _addNotification(notification) {
      var id = this._currentId;
      this._notifications[id] = notification;
      this._currentId++;
      return id;
    }
    /**
    * Removes a notification with the given ID
    * @param  {Integer} id - Dictionary key/ID of the notification to remove
    * @return {Boolean} boolean denoting success
    * @private
    */

  }, {
    key: "_removeNotification",
    value: function _removeNotification(id) {
      var success = false;

      if (this._notifications.hasOwnProperty(id)) {
        /* We're successful if we omit the given ID from the new array */
        delete this._notifications[id];
        success = true;
      }

      return success;
    }
    /**
    * Creates the wrapper for a given notification
    *
    * @param {Integer} id - Dictionary key/ID of the notification
    * @param {Map} options - Options used to create the notification
    * @returns {Map} wrapper hashmap object
    * @private
    */

  }, {
    key: "_prepareNotification",
    value: function _prepareNotification(id, options) {
      var _this = this;

      var wrapper;
      /* Wrapper used to get/close notification later on */

      wrapper = {
        get: function get() {
          return _this._notifications[id];
        },
        close: function close() {
          _this._closeNotification(id);
        }
      };
      /* Autoclose timeout */

      if (options.timeout) {
        setTimeout(function () {
          wrapper.close();
        }, options.timeout);
      }

      return wrapper;
    }
    /**
    * Find the most recent notification from a ServiceWorker and add it to the global array
    * @param notifications
    * @private
    */

  }, {
    key: "_serviceWorkerCallback",
    value: function _serviceWorkerCallback(notifications, options, resolve) {
      var _this2 = this;

      var id = this._addNotification(notifications[notifications.length - 1]);
      /* Listen for close requests from the ServiceWorker */


      if (navigator && navigator.serviceWorker) {
        navigator.serviceWorker.addEventListener('message', function (event) {
          var data = JSON.parse(event.data);
          if (data.action === 'close' && Number.isInteger(data.id)) _this2._removeNotification(data.id);
        });
        resolve(this._prepareNotification(id, options));
      }

      resolve(null);
    }
    /**
    * Callback function for the 'create' method
    * @return {void}
    * @private
    */

  }, {
    key: "_createCallback",
    value: function _createCallback(title, options, resolve) {
      var _this3 = this;

      var notification = null;
      var onClose;
      /* Set empty settings if none are specified */

      options = options || {};
      /* onClose event handler */

      onClose = function onClose(id) {
        /* A bit redundant, but covers the cases when close() isn't explicitly called */
        _this3._removeNotification(id);

        if (Util.isFunction(options.onClose)) {
          options.onClose.call(_this3, notification);
        }
      };
      /* Safari 6+, Firefox 22+, Chrome 22+, Opera 25+ */


      if (this._agents.desktop.isSupported()) {
        try {
          /* Create a notification using the API if possible */
          notification = this._agents.desktop.create(title, options);
        } catch (e) {
          var id = this._currentId;
          var sw = this.config().serviceWorker;

          var cb = function cb(notifications) {
            return _this3._serviceWorkerCallback(notifications, options, resolve);
          };
          /* Create a Chrome ServiceWorker notification if it isn't supported */


          if (this._agents.chrome.isSupported()) {
            this._agents.chrome.create(id, title, options, sw, cb);
          }
        }
        /* Legacy WebKit browsers */

      } else if (this._agents.webkit.isSupported()) notification = this._agents.webkit.create(title, options);else if (this._agents.firefox.isSupported())
        /* Firefox Mobile */
        this._agents.firefox.create(title, options);else if (this._agents.ms.isSupported())
        /* IE9 */
        notification = this._agents.ms.create(title, options);else {
        /* Default fallback */
        options.title = title;
        this.config().fallback(options);
      }

      if (notification !== null) {
        var _id = this._addNotification(notification);

        var wrapper = this._prepareNotification(_id, options);
        /* Notification callbacks */


        if (Util.isFunction(options.onShow)) notification.addEventListener('show', options.onShow);
        if (Util.isFunction(options.onError)) notification.addEventListener('error', options.onError);
        if (Util.isFunction(options.onClick)) notification.addEventListener('click', options.onClick);
        notification.addEventListener('close', function () {
          onClose(_id);
        });
        notification.addEventListener('cancel', function () {
          onClose(_id);
        });
        /* Return the wrapper so the user can call close() */

        resolve(wrapper);
      }
      /* By default, pass an empty wrapper */


      resolve(null);
    }
    /**
    * Creates and displays a new notification
    * @param {Array} options
    * @return {Promise}
    */

  }, {
    key: "create",
    value: function create(title, options) {
      var _this4 = this;

      var promiseCallback;
      /* Fail if no or an invalid title is provided */

      if (!Util.isString(title)) {
        throw new Error(Messages.errors.invalid_title);
      }
      /* Request permission if it isn't granted */


      if (!this.Permission.has()) {
        promiseCallback = function promiseCallback(resolve, reject) {
          _this4.Permission.request().then(function () {
            _this4._createCallback(title, options, resolve);
          }).catch(function () {
            reject(Messages.errors.permission_denied);
          });
        };
      } else {
        promiseCallback = function promiseCallback(resolve, reject) {
          try {
            _this4._createCallback(title, options, resolve);
          } catch (e) {
            reject(e);
          }
        };
      }

      return new Promise(promiseCallback);
    }
    /**
    * Returns the notification count
    * @return {Integer} The notification count
    */

  }, {
    key: "count",
    value: function count() {
      var count = 0;
      var key;

      for (key in this._notifications) {
        if (this._notifications.hasOwnProperty(key)) count++;
      }

      return count;
    }
    /**
    * Closes a notification with the given tag
    * @param {String} tag - Tag of the notification to close
    * @return {Boolean} boolean denoting success
    */

  }, {
    key: "close",
    value: function close(tag) {
      var key, notification;

      for (key in this._notifications) {
        if (this._notifications.hasOwnProperty(key)) {
          notification = this._notifications[key];
          /* Run only if the tags match */

          if (notification.tag === tag) {
            /* Call the notification's close() method */
            return this._closeNotification(key);
          }
        }
      }
    }
    /**
    * Clears all notifications
    * @return {Boolean} boolean denoting whether the clear was successful in closing all notifications
    */

  }, {
    key: "clear",
    value: function clear() {
      var key,
          success = true;

      for (key in this._notifications) {
        if (this._notifications.hasOwnProperty(key)) success = success && this._closeNotification(key);
      }

      return success;
    }
    /**
    * Denotes whether Push is supported in the current browser
    * @returns {boolean}
    */

  }, {
    key: "supported",
    value: function supported() {
      var supported = false;

      for (var agent in this._agents) {
        if (this._agents.hasOwnProperty(agent)) supported = supported || this._agents[agent].isSupported();
      }

      return supported;
    }
    /**
    * Modifies settings or returns all settings if no parameter passed
    * @param settings
    */

  }, {
    key: "config",
    value: function config(settings) {
      if (typeof settings !== 'undefined' || settings !== null && Util.isObject(settings)) Util.objectMerge(this._configuration, settings);
      return this._configuration;
    }
    /**
    * Copies the functions from a plugin to the main library
    * @param plugin
    */

  }, {
    key: "extend",
    value: function extend(manifest) {
      var plugin,
          Plugin,
          hasProp = {}.hasOwnProperty;

      if (!hasProp.call(manifest, 'plugin')) {
        throw new Error(Messages.errors.invalid_plugin);
      } else {
        if (hasProp.call(manifest, 'config') && Util.isObject(manifest.config) && manifest.config !== null) {
          this.config(manifest.config);
        }

        Plugin = manifest.plugin;
        plugin = new Plugin(this.config());

        for (var member in plugin) {
          if (hasProp.call(plugin, member) && Util.isFunction(plugin[member])) // $FlowFixMe
            this[member] = plugin[member];
        }
      }
    }
  }]);
  return Push$$1;
}();

var index = new Push$$1(typeof window !== 'undefined' ? window : global);

return index;

})));
//# sourceMappingURL=push.js.map
