/**********************************************************************
* 
* doc.js
*
* Basic JavaScript self-documentation utils
*
***********************************************/ /* c8 ignore next 2 */
((typeof define)[0]=='u'?function(f){module.exports=f(require)}:define)
(function(require){ var module={} // make module AMD/node compatible...
/*********************************************************************/

module.TAB_SIZE = 4

module.LEADING_TABS = 1


// Normalize code indent...
//
// 	normalizeIndent(text)
// 		-> text
//
//
// This will remove common indent from each line of text, this is useful 
// for printing function code of functions that were defined at deep 
// levels of indent.
//
// This will ignore the indent of the first line.
//
// If the last line is indented higher or equal to the rest of the text 
// we will use leading_tabs (defaults to LEADING_TABS) to indent the 
// rest of the text.
// This will indent the following styles correctnly:
//
// 		|function(a, b){				|function(a, b){
// 		|	return a + b }				|	return a + b
// 		|								|}
//
//
// NOTE: this will trim out both leading and trailing white-space.
// NOTE: this is generally code-agnostic with one sigificant 
// 		exception -- normalizeIndent(..)  will break code written 
// 		in Whitespace.
//
// XXX BUG?
// 			`a					`a						`a
// 			|    b			->	|b			expected?	|    b
// 			|        c`			|    c`					|        c`
// 		while:
// 			`a					`a
// 			|    b			->	|    b		as expected.
// 			|    c`				|    c`
// 		this leads to functions like the following to get messed up:
// 			|function(a){
// 			|	return a
// 			|		|| 'moo' }
//
// XXX is this the right place for this???
// 		...when moving take care that ImageGrid's core.doc uses this...
var normalizeIndent =
module.normalizeIndent =
function(text, {tab_size=module.TAB_SIZE, leading_tabs=module.LEADING_TABS, pad_tabs=0}={}){
	leading_tabs *= tab_size
	var padding = ' '.repeat(pad_tabs*tab_size)
	// prepare text...
	var tab = ' '.repeat(tab_size || 0)
	text = tab != '' ?
		text.replace(/\t/g, tab)
		: text
	// trim the tail and remove leading blank lines...	
	var lines = text.trimEnd().split(/\n/)
	while(lines.length > 0 
			&& lines[0].trim() == ''){
		// XXX we have two options here:
		// 			- indent everyline including the first non-blank
		// 			- do not indent anything (current)
		// 		...not sure which is best...
		leading_tabs = 0
		lines.shift() }
	// count common indent...
	var l = lines 
		.reduce(function(l, e, i){
			var indent = e.length - e.trimLeft().length
			return e.trim().length == 0 
						// ignore 0 indent of first line...
						|| (i == 0 && indent == 0) ?
					l
				// last line...
				: i == lines.length-1
						&& indent >= l ? 
					// XXX feels a bit overcomplicated...
					(l < 0 ?
						// last of two with 0 indent on first -> indent...
						Math.max(indent - leading_tabs, 0)
						// ignore leading_tabs if lower indent...
						: Math.min(l, Math.max(indent - leading_tabs, 0)))
				// initial state...
				: l < 0 ? 
					indent 
				// min...
				: Math.min(l, indent) }, -1) || 0
	// normalize...
	return padding 
		+lines
			.map(function(line, i){
				return i == 0 ? 
					line
					: line.slice(l) })
			.join('\n'+ padding)
			.trim() }


// shorthand more suted for text...
var normalizeTextIndent =
module.normalizeTextIndent =
function(text, opts={leading_tabs: 0}){
	return module.normalizeIndent(text, opts) }


// template string tag versions of the above...
var doc =
module.doc =
function(strings, ...values){
	return normalizeIndent(strings
		.map(function(s, i){ return s + (values[i] || '') })
		.join('')) }

var text =
module.text =
function(strings, ...values){
	return normalizeTextIndent(strings
		.map(function(s, i){ return s + (values[i] || '') })
		.join('')) }



/**********************************************************************
* vim:set ts=4 sw=4 nowrap :                        */ return module })
