/* eslint-disable max-len */

/* eslint-disable no-plusplus */
import PropTypes from "prop-types";
import locales from "./locales";
import defaultLocales from "./default-locales";
import symbols from "./symbols";

var ReactCurrencyFormatter = function ReactCurrencyFormatter(props) {
  var getFormatter = function getFormatter(options) {
    var locale;
    var symbol; // Helper Functions

    var isUndefined = function isUndefined(o) {
      return typeof o === "undefined";
    };

    var toFixed = function toFixed(n, precision) {
      return (+"".concat(Math.round(+"".concat(n, "e").concat(precision)), "e").concat(-precision)).toFixed(precision);
    }; // Perform checks on inputs and set up defaults as needed (defaults to en, USD)


    if (isUndefined(options)) {
      // eslint-disable-next-line no-param-reassign
      options = {};
    }

    var currency = isUndefined(options.currency) ? "USD" : options.currency.toUpperCase();
    locale = isUndefined(options.locale) ? locales[defaultLocales[currency]] : locales[options.locale];
    if (!isUndefined(locale.h)) locale = locales[locale.h]; // Locale inheritance

    symbol = isUndefined(options.symbol) ? symbols[currency] : options.symbol;
    if (isUndefined(symbol)) symbol = currency; // In case we don"t have the symbol, just use the ccy code

    var pattern = isUndefined(options.pattern) ? locale.p : options.pattern;
    var decimal = isUndefined(options.decimal) ? locale.d : options.decimal;
    var group = isUndefined(options.group) ? locale.g : options.group; // encodePattern Function - returns a few simple characteristics of the pattern provided

    var encodePattern = function encodePattern(auxPattern) {
      var decimalPlaces = 0;
      var frontPadding = "";
      var backPadding = "";
      var groupLengths = [];
      var patternStarted = false;
      var decimalsStarted = false;
      var patternEnded = false;
      var currentGroupLength = 0;
      var zeroLength = 0;

      for (var i = 0; i < auxPattern.length; ++i) {
        var c = auxPattern[i];

        if (!patternStarted && ["#", "0", ",", "."].indexOf(c) > -1) {
          patternStarted = true;
        }

        if (!patternStarted) {
          frontPadding += c;
        }

        switch (c) {
          case "#":
            ++currentGroupLength;
            break;

          case "0":
            if (decimalsStarted) ++decimalPlaces;else {
              ++currentGroupLength;
              ++zeroLength;
            }
            break;

          case ",":
            groupLengths.push(currentGroupLength);
            currentGroupLength = 0;
            break;

          case ".":
            groupLengths.push(currentGroupLength);
            decimalsStarted = true;
            break;

          default:
            break;
        }

        if (patternStarted && !(["#", "0", ",", "."].indexOf(c) > -1)) {
          patternEnded = true;

          if (!decimalsStarted) {
            groupLengths.push(currentGroupLength);
          }
        }

        if (patternEnded) {
          backPadding += c;
        }
      }

      var encodedPattern = {
        decimalPlaces: decimalPlaces,
        frontPadding: frontPadding,
        backPadding: backPadding,
        groupLengths: groupLengths,
        zeroLength: zeroLength
      };
      return encodedPattern;
    }; // Zero Padding helper function


    var pad = function pad(n, width) {
      // eslint-disable-next-line no-param-reassign
      n += "";
      return n.length >= width ? n : new Array(width - n.length + 1).join("0") + n;
    }; // Format function


    var format = function format(n, f) {
      var formattedNumber = toFixed(Math.abs(n), f.decimalPlaces);
      var splitNumber = formattedNumber.split(".");
      var segment = ""; // i.e. we actually have some sort of grouping in the values

      if (f.groupLengths.length > 1) {
        var cursor = splitNumber[0].length;
        var groupIndex = f.groupLengths.length - 1;

        while (cursor > 0) {
          if (groupIndex <= 0) {
            groupIndex = 1;
          } // Always reset to the first group length if the number is big


          var currentGroupLength = f.groupLengths[groupIndex];
          var start = cursor - currentGroupLength;
          segment = splitNumber[0].substring(start, cursor) + f.group + segment;
          cursor -= currentGroupLength;
          --groupIndex;
        }

        segment = segment.substring(0, segment.length - 1);
      }

      if (segment.length < f.zeroLength) {
        segment = pad(segment, f.zeroLength);
      }

      formattedNumber = f.frontPadding + segment + (isUndefined(splitNumber[1]) ? "" : f.decimal + splitNumber[1]) + f.backPadding;
      return formattedNumber.replace("!", symbol);
    }; // Use encode function to work out pattern


    var patternArray = pattern.split(";");
    var positiveFormat = encodePattern(patternArray[0]);
    positiveFormat.symbol = symbol;
    positiveFormat.decimal = decimal;
    positiveFormat.group = group;
    var negativeFormat = isUndefined(patternArray[1]) ? encodePattern("-".concat(patternArray[0])) : encodePattern(patternArray[1]);
    negativeFormat.symbol = symbol;
    negativeFormat.decimal = decimal;
    negativeFormat.group = group;
    var zero = isUndefined(patternArray[2]) ? format(0, positiveFormat) : patternArray[2];
    return function (n) {
      var formattedNumber; // eslint-disable-next-line no-param-reassign

      n = Number(n);
      if (n > 0) formattedNumber = format(n, positiveFormat);else if (n === 0) formattedNumber = zero.replace("!", symbol);else formattedNumber = format(n, negativeFormat);
      return formattedNumber;
    };
  };

  var format = function format(number, options) {
    var formatterFunction = getFormatter(options);
    return formatterFunction(number);
  };

  var currency = props.currency,
      symbol = props.symbol,
      locale = props.locale,
      decimal = props.decimal;
  var group = props.group,
      pattern = props.pattern,
      symbolOnly = props.symbolOnly;

  if (symbolOnly) {
    return symbol || symbols[currency];
  }

  var value = format(props.quantity, {
    currency: currency,
    symbol: symbol,
    locale: locale,
    decimal: decimal,
    group: group,
    pattern: pattern
  });

  if (value.indexOf(".") < value.indexOf(",")) {
    return value.replace(",00", "");
  }

  return value.replace(".00", "");
};

ReactCurrencyFormatter.defaultProps = {
  currency: "USD",
  symbolOnly: false,
  quantity: 1
};
ReactCurrencyFormatter.propTypes = {
  symbolOnly: PropTypes.bool,
  quantity: PropTypes.number,
  currency: PropTypes.string,
  symbol: PropTypes.string,
  locale: PropTypes.string,
  decimal: PropTypes.string,
  group: PropTypes.string,
  pattern: PropTypes.string
};
export default ReactCurrencyFormatter;