'use strict';

var fs = require('fs');
var path = require('path');
var gutil = require('gulp-util');
var stripAnsi = require('strip-ansi');
var coveralls = require('gulp-coveralls');
var istanbul = require('gulp-istanbul');
var mocha = require('gulp-mocha');
var relative = require('relative');
var code = require('code-context');
var mdu = require('markdown-utils');
var verb = require('verb');

verb.data({docsDiff: {}, testDiff: {}});

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

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

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

/**
 *
 */

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.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;
}

@@ -386,24 +386,393 @@
 e('verb');%0A%0A
+%0Averb.helper('list', function (pattern) %7B%0A  var files = fs.readdirSync('lib/helpers');%0A  var res = files.reduce(function (acc, fp) %7B%0A    fp = path.resolve('lib/helpers', 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%0Averb.option('debugEngine', true);%0A
 verb.data(%7Bd
@@ -816,15 +816,14 @@
 sk('
-default
+readme
 ', f
@@ -1388,343 +1388,88 @@
 erb.
-helper('list', function (pattern) %7B%0A  var files = fs.readdirSync('lib/helpers');%0A  var res = files.reduce(function (acc, fp) %7B%0A    fp = path.resolve('lib/helpers', 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/**%0A *
+task('default', %5B'readme', 'test'%5D);%0A%0A%0A%0A/**%0A * TODO: move this out into a plugin
 %0A */
@@ -2075,14 +2075,23 @@
 %5Cn+ 
-**
 ' + 
+mdu.strong(
 mdu.
@@ -2100,23 +2100,16 @@
 nk(name,
- './' +
  relativ
@@ -2118,14 +2118,13 @@
 fp))
+)
  + '
-**
 %5Cn';
@@ -2389,15 +2389,8 @@
 hod,
- './' +
  rel
@@ -2531,17 +2531,8 @@
 into
-'%0A    + '
  the

update toc code