'use strict';

// MODULES //

var setReadOnly = require( '@stdlib/utils/define-read-only-property' );
var isObject = require( '@stdlib/assert/is-plain-object' );
var randu = require( '@stdlib/math/base/random/randu' ).factory;
var isnan = require( '@stdlib/math/base/assert/is-nan' );
var validate = require( './validate.js' );
var frechet0 = require( './_frechet.js' );


// MAIN //

/**
* Returns a pseudorandom number generator for generating random numbers drawn from a Fréchet distribution.
*
* @param {PositiveNumber} [alpha] - shape parameter
* @param {PositiveNumber} [s] - scale parameter
* @param {number} [m] - location parameter
* @param {Options} [options] - function options
* @param {*} [options.seed] - pseudorandom number generator seed
* @throws {TypeError} `alpha` must be a positive number
* @throws {TypeError} `s` must be a positive number
* @throws {TypeError} `m` must be a number
* @throws {TypeError} options argument must be an object
* @returns {Function} pseudorandom number generator
*
* @example
* var frechet = factory( 1.0, 1.0, 0.8 );
* var v = frechet();
* // returns <number>
*
* @example
* var frechet = factory( 1.0, 1.0, -2.0, {
*     'seed': 297
* });
* var v = frechet();
* // returns ~-1.074
*/
function factory() {
	var alpha;
	var opts;
	var rand;
	var prng;
	var err;
	var s;
	var m;

	if ( arguments.length === 0 ) {
		rand = randu();
	} else if ( arguments.length === 1 ) {
		opts = arguments[ 0 ];
		if ( !isObject( opts ) ) {
			throw new TypeError( 'invalid input argument. Options argument must be an object. Value: `'+opts+'`.' );
		}
		rand = randu( opts );
	} else {
		alpha = arguments[ 0 ];
		s = arguments[ 1 ];
		m = arguments[ 2 ];
		err = validate( alpha, s, m );
		if ( err ) {
			throw err;
		}
		if ( arguments.length > 3 ) {
			opts = arguments[ 3 ];
			if ( !isObject( opts ) ) {
				throw new TypeError( 'invalid input argument. Options argument must be an object. Value: `' + opts + '`.' );
			}
			rand = randu( opts );
		} else {
			rand = randu();
		}
	}
	if ( alpha === void 0 ) {
		prng = frechet2;
	} else {
		prng = frechet1;
	}
	setReadOnly( prng, 'NAME', 'frechet' );
	setReadOnly( prng, 'SEED', rand.SEED );
	setReadOnly( prng, 'PRNG', rand );

	return prng;

	/**
	* Returns a pseudorandom number drawn from a Fréchet distribution with bound parameters.
	*
	* @private
	* @returns {number} pseudorandom number
	*
	* @example
	* var v = frechet1();
	* // returns <number>
	*/
	function frechet1() {
		return frechet0( rand, alpha, s, m );
	} // end FUNCTION frechet1()

	/**
	* Returns a pseudorandom number drawn from a Fréchet distribution with shape `alpha`, scale `s` and location `m`.
	*
	* @private
	* @param {PositiveNumber} alpha - shape parameter
	* @param {PositiveNumber} s - scale parameter
	* @param {number} m - location parameter
	* @returns {number} pseudorandom number
	*
	* @example
	* var v = frechet2( 2.0, 1.0, 0.5 );
	* // returns <number>
	*
	* @example
	* var v = frechet2( 1.0, 1.0, 0.5 );
	* // returns NaN
	*
	* @example
	* var v = frechet2( 1.0, 2.0, NaN );
	* // returns NaN
	*/
	function frechet2( alpha, s, m ) {
		if (
			isnan( alpha ) ||
			isnan( s ) ||
			isnan( m ) ||
			alpha <= 0.0 ||
			s <= 0.0
		) {
			return NaN;
		}
		return frechet0( rand, alpha, s, m );
	} // end FUNCTION frechet2()
} // end FUNCTION factory()


// EXPORTS //

module.exports = factory;

@@ -2641,16 +2641,17 @@
 cale %60s%60
+,
  and loc

Add Oxford comma