'use strict';

const p = require('path');
const $ = require('./utils');
const flatten = require('flatten');
const Promise = require('bluebird');

const co = Promise.coroutine;
const dirname = p.dirname;
const join = p.join;

const esnext = 'fly-esnext';
const rgx = /^fly-[-\w]+/g;

/**
 * Attempt to dynamically `require()` a file or package
 * @param  {String} name 	The dep-name or filepath to require.
 */
function req(name) {
	try {
		return require(name);
	} catch (e) {
		$.alert(e.message);
	}
}

/**
 * Find a sibling `package.json` file & return its contents.
 * @param  {String} file  The path to `package.json`
 * @return {Array}        The names of all dependencies, flattened
 */
const getDependencies = co(function * (file) {
	if (!file) {
		return [];
	}

	// parse file contents as Object
	const pkg = JSON.parse(yield $.read(file));

	// get all possible dependencies
	const deps = ['dependencies', 'devDependencies', 'peerDependencies']
		.filter(key => key in pkg)
		.map(dep => Object.keys(pkg[dep]));

	return flatten(deps);
});

/**
 * Loads all fly-related plugins!
 * @param  {String} flyfile  The full `flyfile.js` path
 * @return {Array}           All loaded plugins.
 */
const load = co(function * (flyfile) {
	// find `package.json` closes to `flyfile`
	const pkg = yield $.find('package.json', dirname(flyfile));

	if (!pkg) {
		$.error('No `package.json` found!');
		return [];
	}

	const modules = join(dirname(pkg), 'node_modules');

	// get ALL deps; filter down to fly-only; format return;
	return yield getDependencies(pkg)
		.filter(dep => rgx.test(dep))
		.map(str => ({
			name: str,
			plugin: req(join(modules, str))
		}));
});

module.exports = {
	load: load,
	getDependencies: getDependencies
};

@@ -1506,31 +1506,22 @@
 nly;
- format return;%0A%09return
+%0A%09const deps =
  yie
@@ -1543,19 +1543,16 @@
 ies(pkg)
-%0A%09%09
 .filter(
@@ -1572,19 +1572,205 @@
 st(dep))
+;
 %0A%09
-%09
+const hasNext = deps.indexOf(esnext);%0A%0A%09// require fly-esnext; remove from %60deps%60%0A%09if (hasNext !== -1) %7B%0A%09%09deps.splice(hasNext, 1);%0A%09%09require(esnext);%0A%09%7D%0A%0A%09// format return;%0A%09return deps
 .map(str
@@ -1778,17 +1778,16 @@
 =%3E (%7B%0A%09%09
-%09
 name: st
@@ -1789,17 +1789,16 @@
 e: str,%0A
-%09
 %09%09plugin
@@ -1823,17 +1823,16 @@
 , str))%0A
-%09
 %09%7D));%0A%7D)

require 'fly-esnext' if declared