text: (function($, window) {
      'use strict';
  
      var $body = $('body');
  
      $.plugin('swCookiePermission', {
  
          defaults: {
  
              /**
               * Class name to show and hide the cookiePermission element.
               *
               * @property isHiddenClass
               * @type {string}
               */
              isHiddenClass: 'is--hidden',
  
              /**
               * Class name added to body when cookiePermission element is being shown.
               *
               * @property cookieMessageShowingClass
               * @type {string}
               */
              cookieMessageShowingClass: 'cookie--permission--message',
  
              /**
               * Selector of the accept button for select the button and register events on it.
               *
               * @property acceptButtonSelector
               * @type {string}
               */
              acceptButtonSelector: '.cookie-permission--accept-button',
  
              /**
               * Selector of the decline button to select the button and register events on it.
               *
               * @property declineButtonSelector
               * @type {string}
               */
              declineButtonSelector: '.cookie-permission--decline-button',
  
              /**
               * Selector of the cookie consent manager.
               *
               * @property cookieConsentManagerSelector
               * @type {string}
               */
              cookieConsentManagerSelector: '#cookie-consent',
  
              /**
               * Selector of the close button to select the button and register events on it.
               *
               * @property declineButtonSelector
               * @type {string}
               */
              closeButtonSelector: '.cookie-permission--close-button',
  
              /**
               * Selector of the privacy statement link "More information" to select and prepare the href property.
               *
               * @property privacyLinkSelector
               * @type {string}
               */
              privacyLinkSelector: '.cookie-permission--privacy-link',
  
              /**
               * Selector of the hidden input element that contains a cookie group's name.
               * Will be used to check if the cookie preferences are up to date by checking against a hash.
               *
               * @property cookieGroupNameSelector
               * @type {String}
               */
              cookieGroupNameSelector: '.cookie-consent--group-name',
  
              /**
               * Selector of the hidden input element which contains the name of a cookie.
               * Will be used to check if the cookie preferences are up to date by checking against a hash.
               *
               * @property cookieNameSelector
               * @type {String}
               */
              cookieNameSelector: '.cookie-consent--cookie-name',
  
              /**
               * The current shopId for create the storageKey
               *
               * @property shopId
               * @type {number}
               */
              shopId: 0,
  
              /**
               * The shop host url for creating the data privacy statement link
               *
               * @property host
               * @type {string}
               */
              urlPrefix: '',
  
              /**
               * Modal title
               */
              title: ''
          },
  
          /**
           * The key for the local storage. By this key we save the acceptance of the user.
           *
           * @property cookieStorageKeyPrefix
           * @type {string}
           */
          cookieStorageKeyPrefix: 'hide-cookie-permission',
  
          /**
           * Default plugin initialisation function.
           * Sets all needed properties, adds classes and registers all needed event listeners.
           *
           * @public
           * @method init
           */
          init: function() {
              var me = this;
  
              me.applyDataAttributes();
  
              me.createProperties();
              me.preparePrivacyLink();
              me.registerEvents();
              me.displayCookiePermission(function(display) {
                  if (display) {
                      me.showElement();
                  }
              });
          },
  
          /**
           * Calculates the height of the cookie permission element. Please keep in mind that the element has to be
           * visible to get the actual size.
           *
           * @returns {String} height value including the unit e.g. `64px`
           */
          calculatePermissionHeight: function() {
              return this.$el.css('height');
          },
  
          /**
           * Sets the height of the cookie permission messages on the body element as a padding, therefore the message
           * isn't blocking other content.
           *
           * @returns {void}
           */
          setPermissionHeight: function() {
              $body.css('padding-bottom', this.calculatePermissionHeight());
          },
  
          /**
           * Update method which will be automatically called when the user switches the defined breakpoints. The method
           * recalculates the height and updates the `padding-bottom` value of the "body" element
           *
           * @return {void}
           */
          update: function() {
              var me = this;
  
              this.displayCookiePermission(function(display) {
                  if (display) {
                      me.setPermissionHeight();
                  }
              });
          },
  
          /**
           * Creates the required plugin properties
           *
           * @public
           * @method createProperties
           */
          createProperties: function() {
              this.$privacyLink = this.$el.find(this.opts.privacyLinkSelector);
              this.$acceptButton = this.$el.find(this.opts.acceptButtonSelector);
              this.$declineButton = this.$el.find(this.opts.declineButtonSelector);
              this.storageKey = this.createStorageKey();
              this.storage = window.StorageManager.getLocalStorage();
          },
  
          /**
           * Create and set if required a full qualified url as prefix for the privacy link href attribute.
           *
           * @public
           * @method preparePrivacyLink
           */
          preparePrivacyLink: function() {
              var prefix = this.opts.urlPrefix,
                  href;
  
              if (!this.$privacyLink) {
                  return;
              }
  
              href = this.$privacyLink.attr('href') || '';
  
              if (href.match(/^(http:|https:)/)) {
                  return;
              }
  
              if (href.match(/^\//)) {
                  prefix = this.opts.urlPrefix.replace(/(\/)$/, '');
              }
  
              this.$privacyLink.attr('href', [
                  prefix,
                  href
              ].join(''));
          },
  
          /**
           * Subscribes all required events.
           *
           * @public
           * @method registerEvents
           */
          registerEvents: function() {
              this._on(this.$acceptButton, 'click', $.proxy(this.onAcceptButtonClick, this));
              this._on(this.$declineButton, 'click', $.proxy(this.onDeclineButtonClick, this));
          },
  
          /**
           * Validates if cookie permission hint should be shown
           *
           * @param {function} callback
           */
          displayCookiePermission: function(callback) {
              if (window.cookieRemoval === 1) {
                  if ($.getCookie('cookieDeclined')) {
                      callback(false);
                      return;
                  }
  
                  if ($.getCookie('cookiePreferences') && !this.hasPreferencesHashChanged()) {
                      callback(false);
                      return;
                  }
              }
  
              if ((window.cookieRemoval === 2 && document.cookie.indexOf('allowCookie') !== -1)) {
                  callback(false);
                  return;
              }
  
              callback(!this.storage.getItem(this.storageKey));
          },
  
          /**
           * Checks if the hash for the preferences has changed. This happened e.g. when a new cookie
           * was registered by a plugin.
           *
           * @returns { boolean }
           */
          hasPreferencesHashChanged: function () {
              var preferences = JSON.parse($.getCookie('cookiePreferences')),
                  currentHash = preferences.hash,
                  uniqueNames = [],
                  newHash;
  
              $(this.opts.cookieGroupNameSelector).each(function (key, group) {
                  uniqueNames.push($(group).val());
              });
  
              $(this.opts.cookieNameSelector).each(function (key, cookie) {
                  uniqueNames.push($(cookie).val());
              });
  
              uniqueNames.sort();
              newHash = window.btoa(JSON.stringify(uniqueNames));
  
              return newHash !== currentHash;
          },
  
          /**
           * Creates the storageKey from the prefix and the shopId like the following example:
           *
           * hide-cookie-permission-1
           *
           * @public
           * @method createStorageKey
           * @returns {string}
           */
          createStorageKey: function() {
              var delimiter = '-';
  
              return [
                  this.cookieStorageKeyPrefix,
                  delimiter,
                  this.opts.shopId
              ].join('');
          },
  
          /**
           * Event handler for the acceptButton click.
           *
           * @public
           * @method onAcceptButtonClick
           */
          onAcceptButtonClick: function(event) {
              event.preventDefault();
  
              try {
                  window.localStorage.setItem(this.storageKey, 'true');
              } catch (err) {}
  
              var d = new Date();
              d.setTime(d.getTime() + (180 * 24 * 60 * 60 * 1000));
  
              document.cookie = 'allowCookie=1; path=' + this.getBasePath() + ';expires=' + d.toGMTString() + ';' + ($.isSecure() ? ' secure;' : '');
  
              this.hideElement();
  
              $.publish('plugin/swCookiePermission/onAcceptButtonClick', [this, event]);
          },
  
          /**
           * Event handler for the declineButton click.
           *
           * @public
           * @method onDeclineButtonClick
           */
          onDeclineButtonClick: function(event) {
              event.preventDefault();
  
              document.cookie = 'cookieDeclined=1; path=' + this.getBasePath() + ';' + ($.isSecure() ? ' secure;' : '');
  
              this.hideElement();
  
              $.publish('plugin/swCookiePermission/onDeclineButtonClick', [this, event]);
          },
  
          /**
           * Event handler for the closeButton click.
           *
           * @public
           * @method onCloseButtonClick
           */
          onCloseButtonClick: function(event) {
              event.preventDefault();
  
              this.hideElement();
          },
  
          /**
           * Shows the cookiePermission element.
           *
           * @public
           * @method showElement
           */
          showElement: function() {
              if (window.cookieRemoval === 2) {
                  $.modal.open(this.$el.html(), {
                      title: this.opts.title,
                      sizing: 'content',
                      width: 500
                  });
  
                  this.$acceptButton = $(this.opts.acceptButtonSelector);
                  this.$closeButton = $(this.opts.closeButtonSelector);
                  this._on(this.$acceptButton, 'click', $.proxy(this.onAcceptButtonClick, this));
                  this._on(this.$closeButton, 'click', $.proxy(this.onCloseButtonClick, this));
              } else {
                  this.$el.removeClass(this.opts.isHiddenClass);
                  this.setPermissionHeight();
              }
          },
  
          /**
           * Hides the cookiePermission element.
           *
           * @public
           * @method hideElement
           */
          hideElement: function() {
              this.$el.addClass(this.opts.isHiddenClass);
              $body.css('padding-bottom', 0);
              $.modal.close();
          },
  
          getBasePath: function () {
              return window.csrfConfig.basePath || '/';
          }
      });
  }(jQuery, window));
  