"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.writeXMLAsync = writeXMLAsync;
exports.readXMLAsync = readXMLAsync;
exports.parseXMLAsync = parseXMLAsync;
exports.format = format;

function _fsExtra() {
  const data = _interopRequireDefault(require("fs-extra"));

  _fsExtra = function () {
    return data;
  };

  return data;
}

function _os() {
  const data = require("os");

  _os = function () {
    return data;
  };

  return data;
}

function _path() {
  const data = _interopRequireDefault(require("path"));

  _path = function () {
    return data;
  };

  return data;
}

function _xml2js() {
  const data = require("xml2js");

  _xml2js = function () {
    return data;
  };

  return data;
}

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

async function writeXMLAsync(options) {
  const xml = new (_xml2js().Builder)().buildObject(options.xml);
  await _fsExtra().default.ensureDir(_path().default.dirname(options.path));
  await _fsExtra().default.writeFile(options.path, xml);
}

async function readXMLAsync(options) {
  let contents = '';

  try {
    contents = await _fsExtra().default.readFile(options.path, {
      encoding: 'utf8',
      flag: 'r'
    });
  } catch {// catch and use fallback
  }

  const parser = new (_xml2js().Parser)();
  const manifest = await parser.parseStringPromise(contents || options.fallback || '');
  return manifest;
}

async function parseXMLAsync(contents) {
  const xml = await new (_xml2js().Parser)().parseStringPromise(contents);
  return xml;
}

const stringTimesN = (n, char) => Array(n + 1).join(char);

function format(manifest, {
  indentLevel = 2,
  newline = _os().EOL
} = {}) {
  let xmlInput;

  if (typeof manifest === 'string') {
    xmlInput = manifest;
  } else if (manifest.toString) {
    const builder = new (_xml2js().Builder)({
      headless: true
    });
    xmlInput = builder.buildObject(manifest);
    return xmlInput;
  } else {
    throw new Error(`Invalid XML value passed in: ${manifest}`);
  }

  const indentString = stringTimesN(indentLevel, ' ');
  let formatted = '';
  const regex = /(>)(<)(\/*)/g;
  const xml = xmlInput.replace(regex, `$1${newline}$2$3`);
  let pad = 0;
  xml.split(/\r?\n/).map(line => line.trim()).forEach(line => {
    let indent = 0;

    if (line.match(/.+<\/\w[^>]*>$/)) {
      indent = 0;
    } else if (line.match(/^<\/\w/)) {
      // Somehow istanbul doesn't see the else case as covered, although it is. Skip it.

      /* istanbul ignore else  */
      if (pad !== 0) {
        pad -= 1;
      }
    } else if (line.match(/^<\w([^>]*[^/])?>.*$/)) {
      indent = 1;
    } else {
      indent = 0;
    }

    const padding = stringTimesN(pad, indentString);
    formatted += padding + line + newline; // eslint-disable-line prefer-template

    pad += indent;
  });
  return formatted.trim();
}
//# sourceMappingURL=XML.js.map