"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = preProcessPattern;

var _path = _interopRequireDefault(require("path"));

var _isGlob = _interopRequireDefault(require("is-glob"));

var _normalizePath = _interopRequireDefault(require("normalize-path"));

var _normalize = _interopRequireDefault(require("./utils/normalize"));

var _isObject = _interopRequireDefault(require("./utils/isObject"));

var _promisify = require("./utils/promisify");

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

// https://www.debuggex.com/r/VH2yS2mvJOitiyr3
const isTemplateLike = /(\[ext\])|(\[name\])|(\[path\])|(\[folder\])|(\[emoji(:\d+)?\])|(\[(\w+:)?(hash|contenthash)(:\w+)?(:\d+)?\])|(\[\d+\])/;
/* eslint-disable no-param-reassign */

function preProcessPattern(globalRef, pattern) {
  const {
    logger,
    context,
    inputFileSystem,
    fileDependencies,
    contextDependencies,
    compilation
  } = globalRef;
  pattern = typeof pattern === 'string' ? {
    from: pattern
  } : Object.assign({}, pattern);

  if (pattern.from === '') {
    const message = 'path "from" cannot be empty string';
    logger.error(message);
    throw new Error(message);
  }

  pattern.to = pattern.to || '';
  pattern.context = pattern.context || context;

  if (!_path.default.isAbsolute(pattern.context)) {
    pattern.context = _path.default.join(context, pattern.context);
  }

  pattern.context = (0, _normalizePath.default)(pattern.context);
  pattern.ignore = globalRef.ignore.concat(pattern.ignore || []);
  logger.debug(`processing from: '${pattern.from}' to: '${pattern.to}'`);

  switch (true) {
    // if toType already exists
    case !!pattern.toType:
      break;

    case isTemplateLike.test(pattern.to):
      pattern.toType = 'template';
      break;

    case _path.default.extname(pattern.to) === '' || pattern.to.slice(-1) === '/':
      pattern.toType = 'dir';
      break;

    default:
      pattern.toType = 'file';
  } // If we know it's a glob, then bail early


  if ((0, _isObject.default)(pattern.from) && pattern.from.glob) {
    logger.debug(`determined '${pattern.absoluteFrom}' is a glob`);
    pattern.fromType = 'glob';
    const globOptions = Object.assign({}, pattern.from);
    delete globOptions.glob;
    pattern.glob = (0, _normalize.default)(pattern.context, pattern.from.glob);
    pattern.globOptions = globOptions;
    pattern.absoluteFrom = (0, _normalizePath.default)(_path.default.resolve(pattern.context, pattern.from.glob));
    return Promise.resolve(pattern);
  }

  if (_path.default.isAbsolute(pattern.from)) {
    pattern.absoluteFrom = pattern.from;
  } else {
    pattern.absoluteFrom = _path.default.resolve(pattern.context, pattern.from);
  } // Normalize path when path separators are mixed (like `C:\\directory/nested-directory/`)


  pattern.absoluteFrom = (0, _normalizePath.default)(pattern.absoluteFrom);
  logger.debug(`determined '${pattern.from}' to be read from '${pattern.absoluteFrom}'`);

  const noStatsHandler = () => {
    // If from doesn't appear to be a glob, then log a warning
    if ((0, _isGlob.default)(pattern.from) || pattern.from.indexOf('*') !== -1) {
      logger.debug(`determined '${pattern.absoluteFrom}' is a glob`);
      pattern.fromType = 'glob';
      pattern.glob = (0, _normalize.default)(pattern.context, pattern.from); // We need to add context directory as dependencies to avoid problems when new files added in directories
      // when we already in watch mode and this directories are not in context dependencies

      contextDependencies.add(pattern.context);
    } else {
      const newWarning = new Error(`unable to locate '${pattern.from}' at '${pattern.absoluteFrom}'`);
      const hasWarning = compilation.warnings.some( // eslint-disable-next-line no-shadow
      warning => warning.message === newWarning.message); // Only display the same message once

      if (!hasWarning) {
        logger.warn(newWarning.message);
        compilation.warnings.push(newWarning);
      }

      pattern.fromType = 'nonexistent';
    }
  };

  logger.debug(`getting stats for '${pattern.absoluteFrom}' to determinate 'fromType'`);
  return (0, _promisify.stat)(inputFileSystem, pattern.absoluteFrom).catch(() => noStatsHandler()).then(stats => {
    if (!stats) {
      noStatsHandler();
      return pattern;
    }

    if (stats.isDirectory()) {
      logger.debug(`determined '${pattern.absoluteFrom}' is a directory`);
      contextDependencies.add(pattern.absoluteFrom);
      pattern.fromType = 'dir';
      pattern.context = pattern.absoluteFrom;
      pattern.glob = (0, _normalize.default)(pattern.absoluteFrom, '**/*');
      pattern.absoluteFrom = (0, _normalizePath.default)(_path.default.join(pattern.absoluteFrom, '**/*'));
      pattern.globOptions = {
        dot: true
      };
    } else if (stats.isFile()) {
      logger.debug(`determined '${pattern.absoluteFrom}' is a file`);
      fileDependencies.add(pattern.absoluteFrom);
      pattern.fromType = 'file';
      pattern.context = (0, _normalizePath.default)(_path.default.dirname(pattern.absoluteFrom));
      pattern.glob = (0, _normalize.default)(pattern.absoluteFrom);
      pattern.globOptions = {
        dot: true
      };
    } else if (!pattern.fromType) {
      logger.warn(`unrecognized file type for ${pattern.from}`);
    }

    return pattern;
  });
}