text: /**
   * Copyright © Magento, Inc. All rights reserved.
   * See COPYING.txt for license details.
   */
  
  /**
   * @api
   */
  define([
      'jquery',
      'underscore',
      'ko',
      'Magento_Customer/js/section-config',
      'mage/storage',
      'jquery/jquery-storageapi'
  ], function ($, _, ko, sectionConfig) {
      'use strict';
  
      var options,
          storage,
          storageInvalidation,
          invalidateCacheBySessionTimeOut,
          invalidateCacheByCloseCookieSession,
          dataProvider,
          buffer,
          customerData;
  
      //TODO: remove global change, in this case made for initNamespaceStorage
      $.cookieStorage.setConf({
          path: '/'
      });
  
      storage = $.initNamespaceStorage('mage-cache-storage').localStorage;
      storageInvalidation = $.initNamespaceStorage('mage-cache-storage-section-invalidation').localStorage;
  
      /**
       * @param {Object} invalidateOptions
       */
      invalidateCacheBySessionTimeOut = function (invalidateOptions) {
          var date;
  
          if (new Date($.localStorage.get('mage-cache-timeout')) < new Date()) {
              storage.removeAll();
              date = new Date(Date.now() + parseInt(invalidateOptions.cookieLifeTime, 10) * 1000);
              $.localStorage.set('mage-cache-timeout', date);
          }
      };
  
      /**
       * Invalidate Cache By Close Cookie Session
       */
      invalidateCacheByCloseCookieSession = function () {
          if (!$.cookieStorage.isSet('mage-cache-sessid')) {
              $.cookieStorage.set('mage-cache-sessid', true);
              storage.removeAll();
          }
      };
  
      dataProvider = {
  
          /**
           * @param {Object} sectionNames
           * @return {Object}
           */
          getFromStorage: function (sectionNames) {
              var result = {};
  
              _.each(sectionNames, function (sectionName) {
                  result[sectionName] = storage.get(sectionName);
              });
  
              return result;
          },
  
          /**
           * @param {Object} sectionNames
           * @param {Number} updateSectionId
           * @return {*}
           */
          getFromServer: function (sectionNames, updateSectionId) {
              var parameters;
  
              sectionNames = sectionConfig.filterClientSideSections(sectionNames);
              parameters = _.isArray(sectionNames) ? {
                  sections: sectionNames.join(',')
              } : [];
              parameters['update_section_id'] = updateSectionId;
  
              return $.getJSON(options.sectionLoadUrl, parameters).fail(function (jqXHR) {
                  throw new Error(jqXHR);
              });
          }
      };
  
      /**
       * @param {Function} target
       * @param {String} sectionName
       * @return {*}
       */
      ko.extenders.disposableCustomerData = function (target, sectionName) {
          var sectionDataIds, newSectionDataIds = {};
  
          target.subscribe(function () {
              setTimeout(function () {
                  storage.remove(sectionName);
                  sectionDataIds = $.cookieStorage.get('section_data_ids') || {};
                  _.each(sectionDataIds, function (data, name) {
                      if (name != sectionName) { //eslint-disable-line eqeqeq
                          newSectionDataIds[name] = data;
                      }
                  });
                  $.cookieStorage.set('section_data_ids', newSectionDataIds);
              }, 3000);
          });
  
          return target;
      };
  
      buffer = {
          data: {},
  
          /**
           * @param {String} sectionName
           */
          bind: function (sectionName) {
              this.data[sectionName] = ko.observable({});
          },
  
          /**
           * @param {String} sectionName
           * @return {Object}
           */
          get: function (sectionName) {
              if (!this.data[sectionName]) {
                  this.bind(sectionName);
              }
  
              return this.data[sectionName];
          },
  
          /**
           * @return {Array}
           */
          keys: function () {
              return _.keys(this.data);
          },
  
          /**
           * @param {String} sectionName
           * @param {Object} sectionData
           */
          notify: function (sectionName, sectionData) {
              if (!this.data[sectionName]) {
                  this.bind(sectionName);
              }
              this.data[sectionName](sectionData);
          },
  
          /**
           * @param {Object} sections
           */
          update: function (sections) {
              var sectionId = 0,
                  sectionDataIds = $.cookieStorage.get('section_data_ids') || {};
  
              _.each(sections, function (sectionData, sectionName) {
                  sectionId = sectionData['data_id'];
                  sectionDataIds[sectionName] = sectionId;
                  storage.set(sectionName, sectionData);
                  storageInvalidation.remove(sectionName);
                  buffer.notify(sectionName, sectionData);
              });
              $.cookieStorage.set('section_data_ids', sectionDataIds);
          },
  
          /**
           * @param {Object} sections
           */
          remove: function (sections) {
              _.each(sections, function (sectionName) {
                  storage.remove(sectionName);
  
                  if (!sectionConfig.isClientSideSection(sectionName)) {
                      storageInvalidation.set(sectionName, true);
                  }
              });
          }
      };
  
      customerData = {
  
          /**
           * Customer data initialization
           */
          init: function () {
              var countryData,
                  privateContentVersion = 'private_content_version',
                  privateContent = $.cookieStorage.get(privateContentVersion),
                  localPrivateContent = $.localStorage.get(privateContentVersion),
                  needVersion = 'need_version',
                  expiredSectionNames = this.getExpiredSectionNames();
  
              if (privateContent &&
                  !$.cookieStorage.isSet(privateContentVersion) &&
                  !$.localStorage.isSet(privateContentVersion)
              ) {
                  $.cookieStorage.set(privateContentVersion, needVersion);
                  $.localStorage.set(privateContentVersion, needVersion);
                  this.reload([], false);
              } else if (localPrivateContent !== privateContent) {
                  if (!$.cookieStorage.isSet(privateContentVersion)) {
                      privateContent = needVersion;
                      $.cookieStorage.set(privateContentVersion, privateContent);
                  }
                  $.localStorage.set(privateContentVersion, privateContent);
                  this.reload([], false);
              } else if (expiredSectionNames.length > 0) {
                  _.each(dataProvider.getFromStorage(storage.keys()), function (sectionData, sectionName) {
                      buffer.notify(sectionName, sectionData);
                  });
                  this.reload(expiredSectionNames, false);
              } else {
                  _.each(dataProvider.getFromStorage(storage.keys()), function (sectionData, sectionName) {
                      buffer.notify(sectionName, sectionData);
                  });
  
                  if (!_.isEmpty(storageInvalidation.keys())) {
                      this.reload(storageInvalidation.keys(), false);
                  }
              }
  
              if (!_.isEmpty(privateContent)) {
                  countryData = this.get('directory-data');
  
                  if (_.isEmpty(countryData())) {
                      customerData.reload(['directory-data'], false);
                  }
              }
          },
  
          /**
           * Retrieve the list of sections that has expired since last page reload.
           *
           * Sections can expire due to lifetime constraints or due to inconsistent storage information
           * (validated by cookie data).
           *
           * @return {Array}
           */
          getExpiredSectionNames: function () {
              var expiredSectionNames = [],
                  cookieSectionTimestamps = $.cookieStorage.get('section_data_ids') || {},
                  sectionLifetime = options.expirableSectionLifetime * 60,
                  currentTimestamp = Math.floor(Date.now() / 1000),
                  sectionData;
  
              // process sections that can expire due to lifetime constraints
              _.each(options.expirableSectionNames, function (sectionName) {
                  sectionData = storage.get(sectionName);
  
                  if (typeof sectionData === 'object' && sectionData['data_id'] + sectionLifetime <= currentTimestamp) {
                      expiredSectionNames.push(sectionName);
                  }
              });
  
              // process sections that can expire due to storage information inconsistency
              _.each(cookieSectionTimestamps, function (cookieSectionTimestamp, sectionName) {
                  sectionData = storage.get(sectionName);
  
                  if (typeof sectionData === 'undefined' ||
                      typeof sectionData === 'object' &&
                      cookieSectionTimestamp != sectionData['data_id'] //eslint-disable-line
                  ) {
                      expiredSectionNames.push(sectionName);
                  }
              });
  
              return _.uniq(expiredSectionNames);
          },
  
          /**
           * Check if some sections have to be reloaded.
           *
           * @deprecated Use getExpiredSectionNames instead.
           *
           * @return {Boolean}
           */
          needReload: function () {
              var expiredSectionNames = this.getExpiredSectionNames();
  
              return expiredSectionNames.length > 0;
          },
  
          /**
           * Retrieve the list of expired keys.
           *
           * @deprecated Use getExpiredSectionNames instead.
           *
           * @return {Array}
           */
          getExpiredKeys: function () {
              return this.getExpiredSectionNames();
          },
  
          /**
           * @param {String} sectionName
           * @return {*}
           */
          get: function (sectionName) {
              return buffer.get(sectionName);
          },
  
          /**
           * @param {String} sectionName
           * @param {Object} sectionData
           */
          set: function (sectionName, sectionData) {
              var data = {};
  
              data[sectionName] = sectionData;
              buffer.update(data);
          },
  
          /**
           * @param {Array} sectionNames
           * @param {Number} updateSectionId
           * @return {*}
           */
          reload: function (sectionNames, updateSectionId) {
              return dataProvider.getFromServer(sectionNames, updateSectionId).done(function (sections) {
                  $(document).trigger('customer-data-reload', [sectionNames]);
                  buffer.update(sections);
              });
          },
  
          /**
           * @param {Array} sectionNames
           */
          invalidate: function (sectionNames) {
              var sectionDataIds,
                  sectionsNamesForInvalidation;
  
              sectionsNamesForInvalidation = _.contains(sectionNames, '*') ? buffer.keys() : sectionNames;
              $(document).trigger('customer-data-invalidate', [sectionsNamesForInvalidation]);
              buffer.remove(sectionsNamesForInvalidation);
              sectionDataIds = $.cookieStorage.get('section_data_ids') || {};
  
              // Invalidate section in cookie (increase version of section with 1000)
              _.each(sectionsNamesForInvalidation, function (sectionName) {
                  if (!sectionConfig.isClientSideSection(sectionName)) {
                      sectionDataIds[sectionName] += 1000;
                  }
              });
              $.cookieStorage.set('section_data_ids', sectionDataIds);
          },
  
          /**
           * @param {Object} settings
           * @constructor
           */
          'Magento_Customer/js/customer-data': function (settings) {
              options = settings;
              invalidateCacheBySessionTimeOut(settings);
              invalidateCacheByCloseCookieSession();
              customerData.init();
          }
      };
  
      /**
       * Events listener
       */
      $(document).on('ajaxComplete', function (event, xhr, settings) {
          var sections,
              redirects;
  
          if (settings.type.match(/post|put|delete/i)) {
              sections = sectionConfig.getAffectedSections(settings.url);
  
              if (sections) {
                  customerData.invalidate(sections);
                  redirects = ['redirect', 'backUrl'];
  
                  if (_.isObject(xhr.responseJSON) && !_.isEmpty(_.pick(xhr.responseJSON, redirects))) { //eslint-disable-line
                      return;
                  }
                  customerData.reload(sections, true);
              }
          }
      });
  
      /**
       * Events listener
       */
      $(document).on('submit', function (event) {
          var sections;
  
          if (event.target.method.match(/post|put|delete/i)) {
              sections = sectionConfig.getAffectedSections(event.target.action);
  
              if (sections) {
                  customerData.invalidate(sections);
              }
          }
      });
  
      return customerData;
  });
  