(function() {
  var ChunkedScanner, PathReplacer, PathScanner, PathSearcher, globalizeRegex, replace, replaceMain, scanMain, search, searchMain;

  PathSearcher = require('./path-searcher');

  PathScanner = require('./path-scanner');

  PathReplacer = require('./path-replacer');

  ChunkedScanner = require('./chunked-scanner');


  /*
  Single Process
   */

  globalizeRegex = function(regex) {
    var flags;
    if (!regex.global) {
      flags = "g";
      if (regex.ignoreCase) {
        flags += "i";
      }
      if (regex.multiline) {
        flags += "m";
      }
      regex = new RegExp(regex.source, flags);
    }
    return regex;
  };

  search = function(regex, scanner, searcher, doneCallback) {
    var execPathFn;
    regex = globalizeRegex(regex);
    execPathFn = function(filePath, callback) {
      return searcher.searchPath(regex, filePath, callback);
    };
    return new ChunkedScanner(scanner, execPathFn).execute(doneCallback);
  };

  searchMain = function(options) {
    var count, pathCount, resultCount, scanner, searcher;
    searcher = new PathSearcher();
    scanner = new PathScanner(options.pathToScan, options);
    console.time('Single Process Search');
    count = 0;
    resultCount = 0;
    pathCount = 0;
    scanner.on('path-found', function(path) {
      return pathCount++;
    });
    searcher.on('results-found', function(results) {
      var i, len, match, ref, results1;
      count++;
      if (options.verbose) {
        console.log(results.filePath);
      }
      ref = results.matches;
      results1 = [];
      for (i = 0, len = ref.length; i < len; i++) {
        match = ref[i];
        resultCount++;
        if (options.verbose) {
          results1.push(console.log('  ', match.range[0][0] + ":", match.matchText, 'at', match.range));
        } else {
          results1.push(void 0);
        }
      }
      return results1;
    });
    return search(new RegExp(options.search, 'gi'), scanner, searcher, function() {
      console.timeEnd('Single Process Search');
      return console.log(resultCount + " matches in " + count + " files. Searched " + pathCount + " files");
    });
  };

  replace = function(regex, replacement, scanner, replacer, doneCallback) {
    var execPathFn;
    regex = globalizeRegex(regex);
    execPathFn = function(filePath, callback) {
      return replacer.replacePath(regex, replacement, filePath, callback);
    };
    return new ChunkedScanner(scanner, execPathFn).execute(doneCallback);
  };

  replaceMain = function(options) {
    var paths, regex, replacer, scanner, totalFiles, totalReplacements;
    scanner = new PathScanner(options.pathToScan, options);
    replacer = new PathReplacer({
      dryReplace: options.dryReplace
    });
    regex = new RegExp(options.search, 'gi');
    console.time('Single Process Search + Replace');
    paths = [];
    scanner.on('path-found', function(p) {
      return paths.push(p);
    });
    totalReplacements = 0;
    totalFiles = 0;
    replacer.on('path-replaced', function(arg) {
      var filePath, replacements;
      filePath = arg.filePath, replacements = arg.replacements;
      totalFiles++;
      totalReplacements += replacements;
      if (options.verbose) {
        return console.log('Replaced', replacements, 'in', filePath);
      }
    });
    return replace(regex, options.replace, scanner, replacer, function() {
      console.timeEnd('Single Process Search + Replace');
      return console.log("Replaced " + totalReplacements + " matches in " + totalFiles + " files");
    });
  };

  scanMain = function(options) {
    var count, scanner;
    scanner = new PathScanner(options.pathToScan, options);
    console.time('Single Process Scan');
    count = 0;
    scanner.on('path-found', function(path) {
      count++;
      if (options.verbose) {
        return console.log(path);
      }
    });
    scanner.on('finished-scanning', function() {
      console.timeEnd('Single Process Scan');
      return console.log("Found " + count + " paths");
    });
    return scanner.scan();
  };

  module.exports = {
    scanMain: scanMain,
    searchMain: searchMain,
    replaceMain: replaceMain,
    search: search,
    replace: replace
  };

}).call(this);
