/**
 * @module  web-audio-stream/writable
 *
 * Write stream data to web-audio.
 */
'use strict';


var inherits = require('inherits');
var Writable = require('stream').Writable;
var createWriter = require('./write');

module.exports = WAAWritable;


/**
 * @constructor
 */
function WAAWritable (node, options) {
	if (!(this instanceof WAAWritable)) return new WAAWritable(node, options);

	let write = createWriter(node, options);

	Writable.call(this, {
		//we need object mode to recognize any type of input
		objectMode: true,

		//to keep processing delays very short, in case of RT binding.
		//otherwise each stream will hoard data and release only when it’s full.
		highWaterMark: 0,

		write: (chunk, enc, cb) => {
			return write(chunk, cb);
		}
	});


	//manage input pipes number
	this.inputsCount = 0;
	this.on('pipe', (source) => {
		this.inputsCount++;

		//do autoend
		source.once('end', () => {
			this.end()
		});

	}).on('unpipe', (source) => {
		this.inputsCount--;
	})

	//end writer
	this.once('end', () => {
		write.end()
	})
}


inherits(WAAWritable, Writable);


/**
 * Rendering modes
 */
WAAWritable.WORKER_MODE = 2;
WAAWritable.SCRIPT_MODE = 1;
WAAWritable.BUFFER_MODE = 0;


/**
 * There is an opinion that script mode is better.
 * https://github.com/brion/audio-feeder/issues/13
 *
 * But for me there are moments of glitch when it infinitely cycles sound. Very disappointing and makes feel desperate.
 *
 * But buffer mode also tend to create noisy clicks. Not sure why, cannot remove that.
 * With script mode I at least defer my responsibility.
 */
WAAWritable.prototype.mode = WAAWritable.SCRIPT_MODE;


/** Count of inputs */
WAAWritable.prototype.inputsCount = 0;


/**
 * Overrides stream’s end to ensure event.
 */
//FIXME: not sure why `end` is triggered here like 10 times.
WAAWritable.prototype.end = function () {
	if (this.isEnded) return;

	this.isEnded = true;

	var triggered = false;
	this.once('end', () => {
		triggered = true;
	});
	Writable.prototype.end.call(this);

	//timeout cb, because native end emits after a tick
	setTimeout(() => {
		if (!triggered) {
			this.emit('end');
		}
	});

	return this;
};
