// MIT © 2017 azu
// MIT © Zoltan Kochan
// Original https://github.com/zkochan/rcfile
"use strict";

function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

var path = require("path");

var debug = require("debug")("rc-config-loader");

var requireFromString = require("require-from-string");

var JSON5 = require("json5");

var fs = require("fs");

var pathExists = require("path-exists");

var objectAssign = require("object-assign");

var keys = require("object-keys");

var defaultLoaderByExt = {
  ".js": loadJSConfigFile,
  ".json": loadJSONConfigFile,
  ".yaml": loadYAMLConfigFile,
  ".yml": loadYAMLConfigFile
};
var defaultOptions = {
  // does look for `package.json`
  packageJSON: false,
  // treat default(no ext file) as some extension
  defaultExtension: [".json", ".yaml", ".yml", ".js"],
  cwd: process.cwd()
};
/**
 * @param {string} pkgName
 * @param {rcConfigLoaderOption} [opts]
 * @returns {{ config: Object, filePath:string } | undefined}
 */

module.exports = function rcConfigLoader(pkgName) {
  var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  // path/to/config or basename of config file.
  var configFileName = opts.configFileName || ".".concat(pkgName, "rc");
  var defaultExtension = opts.defaultExtension || defaultOptions.defaultExtension;
  var cwd = opts.cwd || defaultOptions.cwd;
  var packageJSON = opts.packageJSON || defaultOptions.packageJSON;
  var packageJSONFieldName = _typeof(packageJSON) === "object" ? packageJSON.fieldName : pkgName;
  var parts = splitPath(cwd);
  var loaders = Array.isArray(defaultExtension) ? defaultExtension.map(function (extension) {
    return defaultLoaderByExt[extension];
  }) : defaultLoaderByExt[defaultExtension];
  var loaderByExt = objectAssign({}, defaultLoaderByExt, {
    "": loaders
  });
  return findConfig({
    parts: parts,
    loaderByExt: loaderByExt,
    configFileName: configFileName,
    packageJSON: packageJSON,
    packageJSONFieldName: packageJSONFieldName
  });
};
/**
 *
 * @param {string[]} parts
 * @param {Object} loaderByExt
 * @param {string} configFileName
 * @param {boolean|Object} packageJSON
 * @param {string} packageJSONFieldName
 * @returns {{
 *  config: string,
 *  filePath: string
 * }|undefined}
 */


function findConfig(_ref) {
  var parts = _ref.parts,
      loaderByExt = _ref.loaderByExt,
      configFileName = _ref.configFileName,
      packageJSON = _ref.packageJSON,
      packageJSONFieldName = _ref.packageJSONFieldName;
  var exts = keys(loaderByExt);

  while (exts.length) {
    var ext = exts.shift();
    var configLocation = join(parts, configFileName + ext);

    if (!pathExists.sync(configLocation)) {
      continue;
    }

    var loaders = loaderByExt[ext];

    if (!Array.isArray(loaders)) {
      var loader = loaders;
      var result = loader(configLocation);

      if (!result) {
        continue;
      }

      return {
        config: result,
        filePath: configLocation
      };
    }

    for (var i = 0; i < loaders.length; i++) {
      var _loader = loaders[i];

      var _result = _loader(configLocation, true);

      if (!_result) {
        continue;
      }

      return {
        config: _result,
        filePath: configLocation
      };
    }
  }

  if (packageJSON) {
    var pkgJSONLoc = join(parts, "package.json");

    if (pathExists.sync(pkgJSONLoc)) {
      var pkgJSON = require(pkgJSONLoc);

      if (pkgJSON[packageJSONFieldName]) {
        return {
          config: pkgJSON[packageJSONFieldName],
          filePath: pkgJSONLoc
        };
      }
    }
  }

  if (parts.pop()) {
    return findConfig({
      parts: parts,
      loaderByExt: loaderByExt,
      configFileName: configFileName,
      packageJSON: packageJSON,
      packageJSONFieldName: packageJSONFieldName
    });
  }

  return undefined;
}

function splitPath(x) {
  return path.resolve(x || "").split(path.sep);
}

function join(parts, filename) {
  return path.resolve(parts.join(path.sep) + path.sep, filename);
}

function loadJSConfigFile(filePath, suppress) {
  debug("Loading JavaScript config file: ".concat(filePath));

  try {
    var content = fs.readFileSync(filePath, "utf-8");
    return requireFromString(content, filePath);
  } catch (e) {
    debug("Error reading JavaScript file: ".concat(filePath));

    if (!suppress) {
      e.message = "Cannot read config file: ".concat(filePath, "\nError: ").concat(e.message);
      throw e;
    }
  }
}

function loadJSONConfigFile(filePath, suppress) {
  debug("Loading JSON config file: ".concat(filePath));

  try {
    return JSON5.parse(readFile(filePath));
  } catch (e) {
    debug("Error reading JSON file: ".concat(filePath));

    if (!suppress) {
      e.message = "Cannot read config file: ".concat(filePath, "\nError: ").concat(e.message);
      throw e;
    }
  }
}

function readFile(filePath) {
  return fs.readFileSync(filePath, "utf8");
}

function loadYAMLConfigFile(filePath, suppress) {
  debug("Loading YAML config file: ".concat(filePath)); // lazy load YAML to improve performance when not used

  var yaml = require("js-yaml");

  try {
    // empty YAML file can be null, so always use
    return yaml.safeLoad(readFile(filePath)) || {};
  } catch (e) {
    debug("Error reading YAML file: ".concat(filePath));

    if (!suppress) {
      e.message = "Cannot read config file: ".concat(filePath, "\nError: ").concat(e.message);
      throw e;
    }
  }
}
//# sourceMappingURL=rc-config-loader.js.map