#!/usr/bin/env node
"use strict";

/* CLI access to vcgrep functionality */

var _ = require('underscore');
var path = require('path');
var shell = require('shelljs');
var matchstick = require('matchstick');

var api = require('./api');

var argv = processArguments();

registerSignalHandlers();

searchFiles(function afterSearchFiles(error, matches) {
  writeOutput(matches);
  exit(matches);
});


function searchFiles(callback) {
  var re = buildRegularExpression();
  var files = findFiles();
  var options = {
    ignoreCase: argv['ignore-case'],
    progress: argv['progress']
  };
  api.searchFiles(re, files, options, callback);
}

function findFiles() {
  var rootFiles = argv._.slice(1);
  return shell.find(rootFiles).filter(findFilesFilter);
}

function findFilesFilter(file) {
  var basename = path.basename(file);
  var include = !argv.include || matchstick(argv.include, 'wildcard').match(basename);
  var exclude = argv.exclude && matchstick(argv.exclude, 'wildcard').match(basename);
  return shell.test('-f', file) && include && !exclude;
}


function writeOutput(matches) {
  var values = matches.values(argv.head);
  api.writeOutput(argv['output'], matches, values);
}

function processArguments() {
  return require('yargs')
    .string('exclude')
    .describe('exclude', 'Exclude files that match the wildcard')
    .boolean('global')
    .alias('global', 'g')
    .describe('global', 'Multiple matches per line are considered')
    .alias('head', 'h')
    .describe('head', 'Limit results to the most frequent n entries')
    .boolean('ignore-case')
    .alias('ignore-case', 'i')
    .describe('ignore-case', 'Ignore case for determining capture key')
    .string('include')
    .describe('include', 'Include only files that match the wildcard')
    .string('output')
    .alias('output', 'o')
    .default('output', api.Output.defaultOption)
    .describe('output', 'Output format, one of: ' + api.Output.options)
    .string('progress')
    .alias('progress', 'p')
    .default('progress', api.Progress.defaultOption)
    .describe('progress', 'Progress feedback, one of: ' + api.Progress.options)
    .boolean('verbose')
    .alias('verbose', 'v')
    .describe('verbose', 'Verbose logging')
    .version(api.version, 'version')
    .strict()
    .demand(2)
    .check(function (argv, options) {
      if (!_.contains(api.Output.options, argv['output'])) {
        throw new Error('Unknown --output value: "' + argv['output'] + '". Should be one of: ' + api.Output.options);
      }
      if (!_.contains(api.Progress.options, argv['progress'])) {
        throw new Error('Unknown --progress value: "' + argv['progress'] + '". Should be one of: ' + api.Progress.options);
      }
    })
    .argv;
}

function buildRegularExpression() {
  var pattern = argv._[0];
  return new RegExp(pattern, argv.global ? 'g' : '');
}

function exit(matches) {
// Follow grep exit status: 0=one or more matches, 1=zero matches, >1 error
  var anyMatches = matches.total > 0;
  process.exit(anyMatches ? 0 : 1);
}

function registerSignalHandlers() {
  process.on('SIGINT', function () {
    console.log('Got a SIGINT. Aborting.');
    process.exit(0);
  });
}
    .usage('Collating grep based on regexp capture with visual progress and result.\nUsage: $0 [OPTIONS] PATTERN FILES...')
    .example('$0 \'(\\d+)\\W+\\d+$\' access.log', 'Count apache http access log lines by response code')
    .example('$0 -g \'(\\w+)+\' README.md', 'Count words in README.md')