
/**
 * Get replacement helper
 */
function getReplacement(replace, isArray, i) {
  if (isArray && typeof replace[i] === 'undefined') {
    return null;
  }
  if (isArray) {
    return replace[i];
  }
  return replace;
}

/**
 * Escape string to make it safe for use in a regex
 */
function escapeRegex(string) {
  if (typeof string === 'string') {
    return string.replace(/[.*+?^${}()|[\]\\/]/g, '\\$&');
  }
  return string;
}

/**
 * Helper to make replacements
 */
module.exports = function makeReplacements(contents, from, to, file, count) {

  //Turn into array
  if (!Array.isArray(from)) {
    from = [from];
  }

  //Check if replace value is an array and prepare result
  const isArray = Array.isArray(to);
  const result = {file};

  //Counting? Initialize number of matches
  if (count) {
    result.numMatches = 0;
    result.numReplacements = 0;
  }

  //Make replacements
  const newContents = from.reduce((contents, item, i) => {

    //Call function if given, passing in the filename
    if (typeof item === 'function') {
      item = item(file);
    }

    //Get replacement value
    let replacement = getReplacement(to, isArray, i);
    if (replacement === null) {
      return contents;
    }

    //Call function if given, appending the filename
    if (typeof replacement === 'function') {
      const original = replacement;
      replacement = (...args) => original(...args, file);
    }

    //Count matches
    if (count) {
      const matches = contents.match(escapeRegex(item));
      if (matches) {
        const replacements = matches.filter(match => match !== replacement);
        result.numMatches += matches.length;
        result.numReplacements += replacements.length;
      }
    }

    //Make replacement
    return contents.replace(item, replacement);
  }, contents);

  //Check if changed
  result.hasChanged = (newContents !== contents);

  //Return result and new contents
  return [result, newContents];
};
