import zeroFill from "../utils/zero-fill.js";
import isFunction from "../utils/is-function.js";
var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|N{1,5}|YYYYYY|YYYYY|YYYY|YY|y{2,4}|yo?|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,
    localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,
    formatFunctions = {},
    formatTokenFunctions = {};
export { formattingTokens, 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 += isFunction(array[i]) ? 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;
}