'use strict';

exports.__esModule = true;
exports.CASE_SENSITIVE_FS = undefined;

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

exports.relative = relative;
exports.default = resolve;

var _es6Map = require('es6-map');

var _es6Map2 = _interopRequireDefault(_es6Map);

var _es6Set = require('es6-set');

var _es6Set2 = _interopRequireDefault(_es6Set);

var _objectAssign = require('object-assign');

var _objectAssign2 = _interopRequireDefault(_objectAssign);

var _pkgDir = require('pkg-dir');

var _pkgDir2 = _interopRequireDefault(_pkgDir);

var _fs = require('fs');

var _fs2 = _interopRequireDefault(_fs);

var _path = require('path');

var path = _interopRequireWildcard(_path);

var _crypto = require('crypto');

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

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

var CASE_SENSITIVE_FS = exports.CASE_SENSITIVE_FS = !_fs2.default.existsSync(path.join(__dirname, 'reSOLVE.js'));

var fileExistsCache = new _es6Map2.default();

function cachePath(cacheKey, result) {
  fileExistsCache.set(cacheKey, { result: result, lastSeen: Date.now() });
}

function checkCache(cacheKey, _ref) {
  var lifetime = _ref.lifetime;

  if (fileExistsCache.has(cacheKey)) {
    var _fileExistsCache$get = fileExistsCache.get(cacheKey);

    var result = _fileExistsCache$get.result;
    var lastSeen = _fileExistsCache$get.lastSeen;
    // check fresness

    if (Date.now() - lastSeen < lifetime * 1000) return result;
  }
  // cache miss
  return undefined;
}

// http://stackoverflow.com/a/27382838
function fileExistsWithCaseSync(filepath, cacheSettings) {
  // don't care if the FS is case-sensitive
  if (CASE_SENSITIVE_FS) return true;

  // null means it resolved to a builtin
  if (filepath === null) return true;

  var dir = path.dirname(filepath);

  var result = checkCache(filepath, cacheSettings);
  if (result != null) return result;

  // base case
  if (dir === '/' || dir === '.' || /^[A-Z]:\\$/i.test(dir)) {
    result = true;
  } else {
    var filenames = _fs2.default.readdirSync(dir);
    if (filenames.indexOf(path.basename(filepath)) === -1) {
      result = false;
    } else {
      result = fileExistsWithCaseSync(dir, cacheSettings);
    }
  }
  cachePath(filepath, result);
  return result;
}

function relative(modulePath, sourceFile, settings) {
  return fullResolve(modulePath, sourceFile, settings).path;
}

function fullResolve(modulePath, sourceFile, settings) {
  // check if this is a bonus core module
  var coreSet = new _es6Set2.default(settings['import/core-modules']);
  if (coreSet != null && coreSet.has(modulePath)) return { found: true, path: null };

  var sourceDir = path.dirname(sourceFile),
      cacheKey = sourceDir + hashObject(settings) + modulePath;

  var cacheSettings = (0, _objectAssign2.default)({
    lifetime: 30 }, settings['import/cache']);

  // parse infinity
  if (cacheSettings.lifetime === '∞' || cacheSettings.lifetime === 'Infinity') {
    cacheSettings.lifetime = Infinity;
  }

  var cachedPath = checkCache(cacheKey, cacheSettings);
  if (cachedPath !== undefined) return { found: true, path: cachedPath };

  function cache(resolvedPath) {
    cachePath(cacheKey, resolvedPath);
  }

  function withResolver(resolver, config) {

    function v1() {
      try {
        var _resolved = resolver.resolveImport(modulePath, sourceFile, config);
        if (_resolved === undefined) return { found: false };
        return { found: true, path: _resolved };
      } catch (err) {
        return { found: false };
      }
    }

    function v2() {
      return resolver.resolve(modulePath, sourceFile, config);
    }

    switch (resolver.interfaceVersion) {
      case 2:
        return v2();

      default:
      case 1:
        return v1();
    }
  }

  var configResolvers = settings['import/resolver'] || { 'node': settings['import/resolve'] }; // backward compatibility

  var resolvers = resolverReducer(configResolvers, new _es6Map2.default());

  var resolved = { found: false };
  resolvers.forEach(function (config, name) {
    if (!resolved.found) {
      var resolver = requireResolver(name, sourceFile);
      resolved = withResolver(resolver, config);
      if (resolved.found) {
        // resolvers imply file existence, this double-check just ensures the case matches
        if (fileExistsWithCaseSync(resolved.path, cacheSettings)) {
          // else, counts
          cache(resolved.path);
        } else {
          resolved = { found: false };
        }
      }
    }
  });

  return resolved;
}

function resolverReducer(resolvers, map) {
  if (resolvers instanceof Array) {
    resolvers.forEach(function (r) {
      return resolverReducer(r, map);
    });
    return map;
  }

  if (typeof resolvers === 'string') {
    map.set(resolvers, null);
    return map;
  }

  if ((typeof resolvers === 'undefined' ? 'undefined' : _typeof(resolvers)) === 'object') {
    for (var key in resolvers) {
      map.set(key, resolvers[key]);
    }
    return map;
  }

  throw new Error('invalid resolver config');
}

function requireResolver(name, sourceFile) {
  // Try to resolve package with conventional name
  try {
    return require('eslint-import-resolver-' + name);
  } catch (err) {} /* continue */

  // Try to resolve package with custom name (@myorg/resolver-name)
  try {
    return require(name);
  } catch (err) {} /* continue */

  // Try to resolve package with path, relative to closest package.json
  // or current working directory
  try {
    var baseDir = _pkgDir2.default.sync(sourceFile) || process.cwd();
    // absolute paths ignore base, so this covers both
    return require(path.resolve(baseDir, name));
  } catch (err) {} /* continue */

  // all else failed
  throw new Error('unable to load resolver "' + name + '".');
}

var erroredContexts = new _es6Set2.default();

/**
 * Given
 * @param  {string} p - module path
 * @param  {object} context - ESLint context
 * @return {string} - the full module filesystem path;
 *                    null if package is core;
 *                    undefined if not found
 */
function resolve(p, context) {
  try {
    return relative(p, context.getFilename(), context.settings);
  } catch (err) {
    if (!erroredContexts.has(context)) {
      context.report({
        message: 'Resolve error: ' + err.message,
        loc: { line: 1, col: 0 }
      });
      erroredContexts.add(context);
    }
  }
}
resolve.relative = relative;

function hashObject(object) {
  var settingsShasum = (0, _crypto.createHash)('sha1');
  settingsShasum.update(JSON.stringify(object));
  return settingsShasum.digest('hex');
}
//# sourceMappingURL=data:application/json;base64,[encoded data, 14140 characters]