/* eslint-disable no-sync */
'use strict';

// MODULES //

var debug = require( 'debug' )( 'repl:help:build' );
var writeFile = require( 'fs' ).writeFileSync;
var resolvePath = require( 'path' ).resolve;
var join = require( 'path' ).join;
var resolve = require( 'resolve' ).sync;
var getKeys = require( 'object-keys' ).shim();
var readFile = require( '@stdlib/fs/read-file' ).sync;
var readJSON = require( '@stdlib/fs/read-json' ).sync;
var resolveParentPath = require( '@stdlib/fs/resolve-parent-path' ).sync;
var dirname = require( '@stdlib/utils/dirname' );
var replace = require( '@stdlib/string/replace' );
var hasOwnProp = require( '@stdlib/assert/has-own-property' );
var namespace = require( '@stdlib/namespace' );


// VARIABLES //

// Create a namespace:
var NAMESPACE = namespace();

// Filepath convention for REPL text:
var REPL_TEXT = 'docs/repl.txt';

// Root search directory:
var ROOT = resolvePath( __dirname, '..', '..', '..' );

// Help docs output file path:
var HELP_OUTPUT = resolvePath( __dirname, '..', 'lib', 'help.js' );

// Output file preamble:
var PREAMBLE = '// This file is generated by scripts/build.js.\n\'use strict\';\n\n/* eslint-disable quotes */\n\n';

// Identifier for inserting 'See Also' links:
var SEE_ALSO = '\n    See Also\n    --------\n';

// Regular expression to detect package aliases:
var RE_ALIASES = /(?:{{alias:[^}]+}})+/g;

// Regular expression to capture a package alias:
var RE_ALIAS = /\{\{alias:([^}]+)\}\}/;


// FUNCTIONS //

/**
* Generates a hash mapping paths to aliases.
*
* @private
* @returns {Object} hash mapping paths to aliases
*/
function aliasMap() {
	var pkg;
	var out;
	var i;

	out = {};
	for ( i = 0; i < NAMESPACE.length; i++ ) {
		pkg = NAMESPACE[ i ];
		out[ pkg.path ] = pkg.alias;
	}
	return out;
} // end FUNCTION aliasMap()

/**
* Returns an array of unique items.
*
* @private
* @param {StringArray} arr - input array of strings
* @returns {StringArray} array containing only unique items
*/
function unique( arr ) {
	var obj;
	var i;

	obj = {};
	for ( i = 0; i < arr.length; i++ ) {
		if ( !hasOwnProp( obj, arr[ i ] ) ) {
			obj[ arr[ i ] ] = true;
		}
	}
	return getKeys( obj );
} // end FUNCTION unique()

/**
* Generates a hash for REPL help text.
*
* @private
*/
function createHelp() {
	var related;
	var aliases;
	var fpath;
	var alias;
	var ropts;
	var fopts;
	var file;
	var pkg;
	var out;
	var len;
	var tmp;
	var a;
	var p;
	var i;
	var j;

	ropts = {
		'basedir': ROOT
	};
	debug( 'Package resolve options: %s', JSON.stringify( ropts ) );

	fopts = {
		'encoding': 'utf8'
	};

	aliases = aliasMap();

	out = {};
	for ( i = 0; i < NAMESPACE.length; i++ ) {
		alias = NAMESPACE[ i ].alias;
		debug( 'Resolving `%s`', alias );

		fpath = resolve( NAMESPACE[ i ].path, ropts );
		debug( 'Resolved module path: %s', fpath );

		debug( 'Resolving package information.' );
		fpath = resolveParentPath( 'package.json', {
			'dir': dirname( fpath )
		});
		if ( fpath === null ) {
			debug( 'Unable to resolve package information.' );
			continue;
		}
		debug( 'Reading package information.' );
		pkg = readJSON( fpath, fopts );
		if ( pkg instanceof Error ) {
			debug( 'Unable to read package information: %s', pkg.message );
			continue;
		}
		debug( 'Checking package information.' );
		if ( pkg.name !== NAMESPACE[ i ].path ) {
			debug( 'Package information does not match path. Expected: %s. Actual: %s.', NAMESPACE[ i ].path, pkg.name );
			continue;
		}
		fpath = join( dirname( fpath ), REPL_TEXT );
		debug( 'Attempting to read REPL text: %s', fpath );

		file = readFile( fpath, fopts );
		if ( file instanceof Error ) {
			debug( 'Unable to read REPL text.' );
			continue;
		}
		debug( 'Successfully read REPL text.' );

		debug( 'Processing REPL text.' );
		file = replace( file, '{{alias}}', alias );

		debug( 'Checking for package identifiers.' );
		tmp = file.match( RE_ALIASES );
		if ( tmp ) {
			debug( 'Resolving package identifier aliases.' );
			tmp = unique( tmp );
			for ( j = 0; j < tmp.length; j++ ) {
				p = RE_ALIAS.exec( tmp[ j ] )[ 1 ]; // extracts a package identifier
				a = aliases[ p ];
				if ( a === void 0 ) {
					debug( 'Unable to resolve alias: %s.', p );
					console.warn( 'WARNING: unable to resolve alias `%s` for `%s`. ', p, alias );
				} else {
					file = replace( file, tmp[ j ], a );
					debug( 'Resolved alias: %s => %s.', p, a );
				}
			}
		}
		debug( 'Resolving related aliases.' );
		len = NAMESPACE[ i ].related.length;
		if ( len ) {
			tmp = [];
			related = NAMESPACE[ i ].related;
			for ( j = 0; j < len; j++ ) {
				a = aliases[ related[ j ] ];
				if ( a === void 0 ) {
					debug( 'Unable to resolve related alias: %s.', related[ j ] );
					console.warn( 'WARNING: unable to resolve related alias `%s` for `%s`. ', related[ j ], alias );
				} else {
					tmp.push( a );
					debug( 'Resolved alias: %s => %s.', related[ j ], a );
				}
			}
			if ( tmp.length ) {
				file = replace( file, SEE_ALSO, SEE_ALSO+'    '+tmp.join( ', ' ) );
			} else {
				file = replace( file, SEE_ALSO, '' );
			}
		} else {
			file = replace( file, SEE_ALSO, '' );
		}
		debug( 'Successfully processed `%s`.', alias );
		out[ alias ] = file;
	}
	debug( 'Writing REPL text hash to file.' );
	out = PREAMBLE+'module.exports = '+JSON.stringify( out, null, '\t' )+';\n';
	writeFile( HELP_OUTPUT, out, fopts );
} // end FUNCTION createHelp()

/**
* Main execution sequence.
*
* @private
*/
function main() {
	debug( 'Generating REPL help documentation.' );
	createHelp();
} // end FUNCTION main()


// MAIN //

main();

@@ -1029,20 +1029,18 @@
 'lib', '
-help
+db
 .js' );%0A

Fix output filename