module.exports = {
	bootstrap : function() {
		_bootstrap();
	}
	,
	processStep : function(ctx, step, next) {
		_processStep(ctx, step, next);
	}
	,
	checkSpec : function(step) {
		_checkSpec(step);
	}
};

// IMPORT
var fs = require('fs');
var util = require('./lib/util.js');

// public variable
var stepDefinitions = [];

// CONSTANTS
var LIB_STEPS_PATH = "lib/steps";

// REGION _bootstrap
var _bootstrap = function() {
	// scan available folders for step definition files
	scanRootLevelFiles();
	scanFolders();
	scanNodeModules();
}
var scanRootLevelFiles = function() {
	var list = fs.readdirSync(__dirname + "/" + LIB_STEPS_PATH);
	list.forEach(function(filename) {
		if(filename.lastIndexOf('.js') > -1) {
			var filepath = './' + LIB_STEPS_PATH + '/' + filename;
			delete require.cache[require.resolve(filepath)]; // delete require cache
			var def = require(filepath);
			var name = filename.replace('.js', '');
			if(typeof stepDefinitions[name] != 'undefined') {
				throw new Error('ERROR the step definition [' + name + '] exist');
			}
			stepDefinitions[name] = def;
		}
	});
}
var scanFolders = function() {
	var list = fs.readdirSync(__dirname + "/" + LIB_STEPS_PATH);
	list.forEach(function(folder) {
		if(folder.lastIndexOf('.js') == -1) {
			var filepath = './' + LIB_STEPS_PATH + '/' + folder + '/init.js';
			delete require.cache[require.resolve(filepath)]; // delete require cache
			var def = require(filepath);
			var name = folder;
			if(typeof stepDefinitions[name] != 'undefined') {
				throw new Error('ERROR the step definition [' + name + '] exist');
			}
			stepDefinitions[name] = def;
		}
	});
}
var scanNodeModules = function() {
	//TODO
}
// ENDREGION _bootstrap
// REGION _checkSpec
var _checkSpec = function(step) {
	var pro = new StepProcessor({}, step, function() {});
	pro.checkSpec(step);
}
// ENDREGION _checkSpec
// REGION _processStep

var _processStep = function(ctx, step, next) {
	var pro = new StepProcessor(ctx, step, next);
	pro.process();
}
var StepProcessor = function(ctx, step, next) {
	this.ctx = ctx;
	this.step = step;
	
	var def = null;
	var spec = null;
	var init = function() {
		findDef();
		findSpec();
	}
	
	var findDef = function() {
		if(typeof stepDefinitions[step.type] != 'undefined') {
			def = stepDefinitions[step.type];
		}
	}
	var findSpec = function() {
		if(def == null) return;
		if(typeof def.spec == 'undefined') {
			console.log('Error spec function is missing for ' + step.type);
			throw new Error("Error spec function is missing for " + step.type);
		}
		spec = def.spec();
		if(spec == null) {
			throw new Error("Spec is null");
		}
		if(typeof def.process == 'undefined') {
			console.log('Error process function is missing for ' + step.type);
			throw new Error('Error process function is missing for ' + step.type);
		}
	}
	var checkSpec = function(step) {
		if(spec == null) {
			return;
		}
		// checkRequired Fields
		spec.fields.forEach(function(field) {
			if(field.required) {
				if(typeof step[field.name] == 'undefined') {
					console.log('Error step did not have required field ' + field.name);
					throw new Error('Error step did not have required field ' + field.name);
				}
			}
		});
	}
	this.checkSpec = checkSpec;
	this.process = function() {
		if(def == null) {
			process.nextTick(next);
			return; // if def not found, silent exit
		}
		//checkSpec(step);
		def.process(ctx, step, next);
	}
	init();
}

// ENDREGION _processStep
@@ -1,8 +1,108 @@
+// IMPORT%0Avar fs = require('fs');%0Avar util = require('./lib/util.js');%0Avar path = require('path');%0A%0A
 module.e
@@ -303,80 +303,8 @@
 %7D;%0A%0A
-// IMPORT%0Avar fs = require('fs');%0Avar util = require('./lib/util.js');%0A%0A
 // p
@@ -615,32 +615,42 @@
  fs.readdirSync(
+path.join(
 __dirname + %22/%22 
@@ -638,32 +638,25 @@
 in(__dirname
- + %22/%22 +
+,
  LIB_STEPS_P
@@ -651,33 +651,35 @@
  LIB_STEPS_PATH)
-;
+); 
 %0A%09list.forEach(f
@@ -1178,16 +1178,26 @@
 dirSync(
+path.join(
 __dirnam
@@ -1201,16 +1201,9 @@
 name
- + %22/%22 +
+,
  LIB
@@ -1214,16 +1214,17 @@
 PS_PATH)
+)
 ;%0A%09list.
@@ -1283,16 +1283,17 @@
 .js') ==
+=
  -1) %7B%0A%09
@@ -1519,32 +1519,33 @@
 nitions%5Bname%5D !=
+=
  'undefined') %7B%0A
@@ -2369,24 +2369,25 @@
 %0A%09%09if(def ==
+=
  null) retur
@@ -2595,32 +2595,33 @@
 ();%0A%09%09if(spec ==
+=
  null) %7B%0A%09%09%09thro
@@ -2679,16 +2679,17 @@
 ocess ==
+=
  'undefi
@@ -2893,16 +2893,17 @@
 (spec ==
+=
  null) %7B
@@ -3041,16 +3041,17 @@
 name%5D ==
+=
  'undefi
@@ -3299,16 +3299,17 @@
 f(def ==
+=
  null) %7B
@@ -3388,29 +3388,8 @@
 %09%09%7D%0A
-%09%09//checkSpec(step);%0A
 %09%09de

fix #60