'use strict';

// MODULES //

var parseJSDoc = require( 'doctrine' ).parse;
var copy = require( '@stdlib/utils/copy' );
var isObject = require( '@stdlib/assert/is-object' );
var hasOwnProp = require( '@stdlib/assert/has-own-property' );
var startsWith = require( '@stdlib/string/starts-with' );
var isCapitalized = require( '@stdlib/assert/is-capitalized' );
var endsWith = require( '@stdlib/string/ends-with' );
var findJSDoc = require( '@stdlib/_tools/eslint/utils/find-jsdoc' );
var DEFAULTS = require( './defaults.json' );


// VARIABLES //

var DOPTS = {
	'sloppy': true,
	'unwrap': true
};
var RE_NUM = /^\d/;
var rule;


// FUNCTIONS //

/**
* Rule for validating that JSDoc descriptions start with an uppercase letter or number and end with a period.
*
* @param {Object} context - ESLint context
* @returns {Object} validators
*/
function main( context ) {
	var options;
	var source;
	var opts;

	opts = copy( DEFAULTS );
	options = context.options[ 0 ];
	if ( hasOwnProp( options, 'whitelist' ) ) {
		opts.whitelist = options.whitelist;
	}
	source = context.getSourceCode();

	return {
		'FunctionExpression:exit': validate,
		'FunctionDeclaration:exit': validate,
		'VariableDeclaration:exit': validate,
		'ExpressionStatement:exit': validate
	};

	/**
	* Checks whether JSDoc comments have a capitalized description that ends with a period.
	*
	* @private
	* @param {ASTNode} node - AST node
	* @returns {void}
	*/
	function validate( node ) {
		var found;
		var jsdoc;
		var desc;
		var word;
		var idx;
		var ast;
		var i;

		jsdoc = findJSDoc( source, node );
		if ( isObject( jsdoc ) ) {
			ast = parseJSDoc( jsdoc.value, DOPTS );
			desc = ast.description;
			idx = desc.indexOf( '\n' );
			if ( idx !== -1 ) {
				// Only first line contains the description:
				desc = desc.substr( 0, idx );
			}
			// Do not raise an error for JSDoc comments without descriptions:
			if ( desc.length ) {
				if ( !endsWith( desc, '.' ) ) {
					return report( jsdoc.loc );
				}
				if ( !isCapitalized( desc ) && !desc.match( RE_NUM ) ) {
					// Check whether description starts with a word from the whitelist:
					found = false;
					for ( i = 0; i < opts.whitelist.length; i++ ) {
						word = opts.whitelist[ i ];
						if ( startsWith( desc, word+' ' ) ) {
							found = true;
							break;
						}
					}
					// If not, raise an error:
					if ( !found ) {
						report( jsdoc.loc );
					}
				}
			}
		}
	}

	/**
	* Reports the error message.
	*
	* @private
	* @param {Object} loc - lines of code (object with `start` and `end` properties)
	*/
	function report( loc ) {
		context.report({
			'node': null,
			'message': 'Description must start with an uppercase letter or number and end with a period',
			'loc': loc
		});
	}
}


// MAIN //

rule = {
	'meta': {
		'docs': {
			'description': 'enforce that JSDoc descriptions start with an uppercase letter or number and end with a period'
		},
		'schema': [
			{
				'type': 'object',
				'properties': {
					'whitelist': {
						'type': 'array'
					}
				},
				'additionalProperties': false
			}
		]
	},
	'create': main
};


// EXPORTS //

module.exports = rule;

@@ -609,16 +609,51 @@
  /%5E%5Cd/;%0A
+var slice = Array.prototype.slice;%0A
 var rule
@@ -1054,16 +1054,28 @@
 telist =
+ slice.call(
  options
@@ -1084,16 +1084,18 @@
 hitelist
+ )
 ;%0A%09%7D%0A%09so

Make a copy of whitelist