/**
*
*	STREAM: histc
*
*
*
*	DESCRIPTION:
*		- 
*
*
*	API:
*		- 
*
*
*	NOTES:
*		[1] 
*
*
*	TODO:
*		[1] 
*
*
*	HISTORY:
*		- 2014/05/17: Created. [AReines].
*
*
*	DEPENDENCIES:
*		[1] 
*
*
*	LICENSE:
*		MIT
*
*	Copyright (c) 2014. Athan Reines.
*
*
*	AUTHOR:
*		Athan Reines. athan@nodeprime.com. 2014.
*
*/

(function() {
	'use strict';

	// MODULES //

	var // Module to combine streams:
		pipeline = require( 'stream-combiner' ),

		// Stream transform:
		transformer = require( './../../transform' ),

		// Stream reduce:
		reducer = require( './../../reduce' ),

		// Module to determine bin location:
		getBin = require( './binarysearch.js' );


	// FUNCTIONS //

	/**
	* FUNCTION: linspace( min, max, increment )
	*	Generate a linearly spaced vector.
	*
	* @private
	* @param {number} min - min defines the vector lower bound
	* @param {number} max - max defines the vector upper bound
	* @param {number} increment - distance between successive vector elements
	* @returns {array} a 1-dimensional array
	*/
	function linspace( min, max, increment ) {
		var numElements, vec = [];

		numElements = Math.round( ( ( max - min ) / increment ) ) + 1;

		vec[ 0 ] = min;
		vec[ numElements - 1] = max;

		for ( var i = 1; i < numElements - 1; i++ ) {
			vec[ i ] = min + increment*i;
		}
		return vec;
	} // end FUNCTION linspace()

	/**
	* FUNCTION: newCounts( edges )
	*	Initializes a new histogram counts array.
	*
	* @private
	* @param {array} edges - 1d array defining the bins in which to tabulate data.
	* @returns {array} counts array (note: array length is edges.length+1 to include -/+ infinity bins, i.e., data outside of defined edge range, and each array element is a 3-element array: [ prev_edge | count | edge ] )
	*/
	function newCounts( edges ) {
		var numBins = edges.length + 1,
			counts = new Array( numBins );

		for ( var i = 0; i < numBins; i++ ) {
			counts[ i ] = [
				edges[ i-1 ],
				0,
				edges[ i ]
			];
		} // end FOR i
		return counts;
	} // end FUNCTION newCounts()

	/**
	* FUNCTION: stringify( data )
	*	Defines the data transformation.
	*
	* @private
	* @param {array} data - streamed data
	* @returns {string} stringified data
	*/
	function stringify( data ) {
		return JSON.stringify( data );
	} // end FUNCTION stringify()

	/**
	* FUNCTION: transform( edges )
	*	Returns a data transformation function.
	*
	* @private
	* @param {array} edges - 1d array containing histogram bin edges
	* @returns {function} data transformation function
	*/
	function transform( edges ) {
		/**
		* FUNCTION: transform( data )
		*	Defines the data transformation.
		*
		* @param {number} data - numeric stream data
		* @returns {number} transformed data
		*/
		return function transform( data ) {
			return getBin( edges, data );
		};
	} // end FUNCTION transform()

	/**
	* FUNCTION: reduce( acc, data )
	*	Defines the data reduction.
	*
	* @private
	* @param {array} acc - accumulation array
	* @param {number} idx - streamed bin index
	* @returns {array} accumulation array
	*/
	function reduce( counts, idx ) {
		counts[ idx ][ 1 ] += 1;
		return counts;
	} // end FUNCTION reduce()


	// STREAM //

	/**
	* FUNCTION: Stream()
	*	Stream constructor.
	*
	* @returns {object} Stream instance
	*/
	function Stream() {
		this._edges = linspace( -0.01, 1.01, 0.02 );
		return this;
	} // end FUNCTION stream()

	/**
	* METHOD: edges( vector )
	*	Edges setter and getter. If a vector is supplied, sets edges. If no vector is supplied, returns the edges.
	*
	* @param {array} vector - edges
	* @returns {object|vector} instance object or edges
	*/
	Stream.prototype.edges = function ( vector ) {
		if ( !arguments.length ) {
			return this._edges;
		}
		if ( !Array.isArray( edges ) ) {
			throw new Error( 'edges()::invalid input argument. Edges must be an array.' );
		}
		this._edges = vector;
		return this;
	}; // end METHOD edges()

	/**
	* METHOD: stream()
	*	Returns a JSON data transform stream for calculating the statistic.
	*/
	Stream.prototype.stream = function() {
		var iStream, counts, rStream, sStream, pStream;

		// Create an input transform stream:
		iStream = transformer( transform( this._edges ) );

		// Initialize a new counts array:
		counts = newCounts( this._edges );

		// Create a reduction stream to tabulate data values:
		rStream = reducer( reduce, counts );

		// Create a transform stream to stringify tabulated data:
		sStream = transformer( stringify );

		// Create a stream pipeline:
		pStream = pipeline(
			iStream,
			rStream,
			sStream
		);

		// Return the pipeline:
		return pStream;
	}; // end METHOD stream()


	// EXPORTS //

	module.exports = function createStream() {
		return new Stream();
	};

})();
@@ -2004,271 +2004,8 @@
 ()%0A%0A
-%09/**%0A%09* FUNCTION: stringify( data )%0A%09*%09Defines the data transformation.%0A%09*%0A%09* @private%0A%09* @param %7Barray%7D data - streamed data%0A%09* @returns %7Bstring%7D stringified data%0A%09*/%0A%09function stringify( data ) %7B%0A%09%09return JSON.stringify( data );%0A%09%7D // end FUNCTION stringify()%0A%0A
 %09/**
@@ -3770,17 +3770,8 @@
 eam,
- sStream,
  pSt
@@ -4044,107 +4044,8 @@
 );%0A%0A
-%09%09// Create a transform stream to stringify tabulated data:%0A%09%09sStream = transformer( stringify );%0A%0A
 %09%09//
@@ -4119,20 +4119,8 @@
 ream
-,%0A%09%09%09sStream
 %0A%09%09)

remove stringify transform from histc stream.