text: import zeroFill from '../utils/zero-fill';
  
  export var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g;
  
  var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g;
  
  var formatFunctions = {};
  
  export var formatTokenFunctions = {};
  
  // token:    'M'
  // padded:   ['MM', 2]
  // ordinal:  'Mo'
  // callback: function () { this.month() + 1 }
  export function addFormatToken (token, padded, ordinal, callback) {
      var func = callback;
      if (typeof callback === 'string') {
          func = function () {
              return this[callback]();
          };
      }
      if (token) {
          formatTokenFunctions[token] = func;
      }
      if (padded) {
          formatTokenFunctions[padded[0]] = function () {
              return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
          };
      }
      if (ordinal) {
          formatTokenFunctions[ordinal] = function () {
              return this.localeData().ordinal(func.apply(this, arguments), token);
          };
      }
  }
  
  function removeFormattingTokens(input) {
      if (input.match(/\[[\s\S]/)) {
          return input.replace(/^\[|\]$/g, '');
      }
      return input.replace(/\\/g, '');
  }
  
  function makeFormatFunction(format) {
      var array = format.match(formattingTokens), i, length;
  
      for (i = 0, length = array.length; i < length; i++) {
          if (formatTokenFunctions[array[i]]) {
              array[i] = formatTokenFunctions[array[i]];
          } else {
              array[i] = removeFormattingTokens(array[i]);
          }
      }
  
      return function (mom) {
          var output = '', i;
          for (i = 0; i < length; i++) {
              output += array[i] instanceof Function ? array[i].call(mom, format) : array[i];
          }
          return output;
      };
  }
  
  // format date using native date object
  export function formatMoment(m, format) {
      if (!m.isValid()) {
          return m.localeData().invalidDate();
      }
  
      format = expandFormat(format, m.localeData());
      formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format);
  
      return formatFunctions[format](m);
  }
  
  export function expandFormat(format, locale) {
      var i = 5;
  
      function replaceLongDateFormatTokens(input) {
          return locale.longDateFormat(input) || input;
      }
  
      localFormattingTokens.lastIndex = 0;
      while (i >= 0 && localFormattingTokens.test(format)) {
          format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
          localFormattingTokens.lastIndex = 0;
          i -= 1;
      }
  
      return format;
  }
  