'use strict';

var gutil = require('gulp-util');
var coveralls = require('gulp-coveralls');
var istanbul = require('gulp-istanbul');
var jshint = require('gulp-jshint');
var mocha = require('gulp-mocha');

var fs = require('fs');
var path = require('path');
var stripAnsi = require('strip-ansi');
var code = require('code-context');
var mdu = require('markdown-utils');
var relative = require('relative');
var verb = require('verb');


verb.helper('list', function (dir) {
  var files = fs.readdirSync(dir);
  var res = files.reduce(function (acc, fp) {
    fp = path.resolve(dir, fp);
    if (!/index\.js/.test(fp) && /\.js/.test(fp)) {
      acc[fp] = require(fp);
    }
    return acc;
  }, {});
  return format(res).replace(/^\s*/, '');
});

verb.option('debugEngine', true);
verb.data({docsDiff: {}, testDiff: {}});

verb.task('readme', function() {
  verb.src('.verb.md')
    .pipe(verb.dest('.'));
});

verb.task('lint', function () {
  verb.src(['index.js', 'lib/**/*.js'])
    .pipe(jshint('.jshintrc'))
    .pipe(jshint.reporter('jshint-stylish'));
});

verb.task('test', function (cb) {
  verb.src(['index.js', 'lib/**/*.js'])
    .pipe(istanbul({includeUntested: true}))
    .pipe(istanbul.hookRequire())
    .on('finish', function () {
      verb.src('test/*.js')
        .on('error', gutil.log)
        .pipe(mocha())
        .pipe(istanbul.writeReports())
        .on('end', cb);
    });
});

verb.task('default', ['readme', 'lint', 'test']);



/**
 * TODO: move this out into a plugin
 */

function summary(fp) {
  var str = fs.readFileSync(fp, 'utf8');
  str = stripAnsi(str).replace(/^=.*/gm, '');
  return str;
}


function context(str) {
  return code(str).reduce(function (acc, ele) {
    if (ele && ele.type !== 'comment') {
      acc[ele.name] = ele.begin;
    }
    return acc;
  }, {});
}

function format(obj) {
  var keys = Object.keys(obj);
  var len = keys.length;
  var i = 0;
  var res = '\n';
  var count = len;

  while (len--) {
    var fp = keys[i++];
    var ctx = context(fs.readFileSync(fp, 'utf8'));
    var name = path.basename(fp, path.extname(fp));
    res += '\n+ ' + mdu.strong(mdu.link(name, relative(fp))) + '\n';

    var list = obj[fp];
    var items = Object.keys(list);
    // todo: move this to a new function
    res += items.map(function (method) {
      count++;
      var line = ctx[method];
      var link = method;
      if (line) {
        link = mdu.link(method, relative(fp) + '#L' + line);
      }
      return '  - ' + link;
    }).sort().join('\n');
  }

  return count
    + ' helpers organized into the following categories:'
    + res;
}

@@ -46,51 +46,8 @@
 ');%0A
-var coveralls = require('gulp-coveralls');%0A
 var 
@@ -212,47 +212,8 @@
 ');%0A
-var stripAnsi = require('strip-ansi');%0A
 var 
@@ -350,319 +350,8 @@
 );%0A%0A
-%0Averb.helper('list', function (dir) %7B%0A  var files = fs.readdirSync(dir);%0A  var res = files.reduce(function (acc, fp) %7B%0A    fp = path.resolve(dir, fp);%0A    if (!/index%5C.js/.test(fp) && /%5C.js/.test(fp)) %7B%0A      acc%5Bfp%5D = require(fp);%0A    %7D%0A    return acc;%0A  %7D, %7B%7D);%0A  return format(res).replace(/%5E%5Cs*/, '');%0A%7D);%0A%0A
 verb
@@ -453,24 +453,31 @@
 ction() %7B%0A  
+return 
 verb.src('.v
@@ -547,24 +547,31 @@
 tion () %7B%0A  
+return 
 verb.src(%5B'i
@@ -878,16 +878,17 @@
 erb.src(
+%5B
 'test/*.
@@ -890,16 +890,40 @@
 st/*.js'
+%5D)%0A        .pipe(mocha()
 )%0A      
@@ -948,39 +948,16 @@
 il.log)%0A
-        .pipe(mocha())%0A
         
@@ -1013,23 +1013,22 @@
  cb)
-;
 %0A    %7D)
-;
 %0A%7D);%0A%0A
+%0A
 verb
@@ -1080,139 +1080,290 @@
 %0A%0A%0A%0A
-/**%0A * TODO: move this out into a plugin%0A */%0A%0Afunction summary(fp) %7B%0A  var str = fs.readFileSync(fp, 'utf8');%0A  str = stripAnsi(str
+verb.helper('list', function (dir) %7B%0A  var files = fs.readdirSync(dir);%0A  var res = files.reduce(function (acc, fp) %7B%0A    fp = path.resolve(dir, fp);%0A    if (!/index%5C.js/.test(fp) && /%5C.js/.test(fp)) %7B%0A      acc%5Bfp%5D = require(fp);%0A    %7D%0A    return acc;%0A  %7D, %7B%7D);%0A  return format(res
 ).re
@@ -1374,37 +1374,69 @@
 e(/%5E
-=.*/gm
+%5Cs*/
 , '');%0A
-  return str;%0A%7D%0A
+%7D);%0A%0A%0A/**%0A * TODO: move this out into a plugin%0A */
 %0A%0Afu

clean up