Source: response/defaultResponseManager.js

/**
 * @author Sloan Seaman 
 * @copyright 2016 and on
 * @version .1
 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
 */

/** @private */
var AbstractProviderManager = require('../provider/abstractProviderManager.js');
var DefaultResponseBuilder = require('./DefaultResponseBuilder.js');
var HandlebarsFormatterManager = require('./formatter/HandlebarsFormatterManager.js');

/**
 * Manages responses
 *
 * @constructor
 * @implements {ResponseManager}
 * @param {Array.Provider} [providers] An array of response providers that will supply responses
 */
function DefaultResponseManager(providers) {
	this._responses = {};
	this._notFound = {};

	this._askResponse = new DefaultResponseBuilder()
		.withFormatterManager(new HandlebarsFormatterManager())
		.withJSON(
			{ 
				"custom" : {
					"response" : {
						"outputSpeech" : {
							"text": "{{msg}}"
						}
					},
					"reprompt" : {
						"outputSpeech" : {
							"text" : "{{reprompt}}"
						}
					},
				}
			}
		)
		.build();

	this._tellResponse = new DefaultResponseBuilder()
		.withFormatterManager(new HandlebarsFormatterManager())
		.withJSON(
			{ 
				"custom" : {
					"response" : {
						"outputSpeech" : {
							"text": "{{msg}}"
						} 
					}
				}
			}
		)
		.build();
	
	AbstractProviderManager.apply(this, [providers]);
}

DefaultResponseManager.prototype = Object.create(AbstractProviderManager.prototype);
DefaultResponseManager.prototype.constructor = DefaultResponseManager;

/**
 * Returns the specified response by looking through the defined providers.
 *
 * Optimized to only look once and if not found, will never look through the provider again.  This prevents
 * adding responses to the provider at a later time, but improves repeated lookup performance
 *
 * @function
 * @param  {String} responseId The id of the response
 * @return {Response} The response.  If not found, returns null
 */
DefaultResponseManager.prototype.get = function(responseId) {
	var response = this._responses[responseId];

	if (!response && !this._notFound[responseId]) { // response isn't in cache and was never looked for
		var providers = this.getRegisteredProviders();

		for (var i=0;i<providers.length;i++) {
			// This could be expensive at is could cause all of the file loading to occur when looking for a response
			response = providers[i].getItem(responseId);

			if (response) {
				this._responses[responseId] = response; // found it. set it so I never have to look again
				break; // hop out if I find it
			}
		}
		if (response === null) this._notFound[responseId] = true; // never will find it, so record this fact so we don't ever look again
	}

	return response;
};

/**
 * Helper method that retrieves and renders a response all in one call
 * 
 * @param  {String} responseId The id of the response
 * @param  {Object.<String,Object>} valuesMap The values to use when formatting the response
 * @return {String} The rendered string to send back to Alexa
 */
DefaultResponseManager.prototype.render = function(responseId, valuesMap) {
	var response = this.get(responseId);
	if (!response) {
		throw new Error('Could not find response with id '+responseId);
	}
	return response.render(valuesMap);
};

/**
 * Helper method to do an ask similar to the alexa api
 * @param  {String} msg      The message to ask to the user
 * @param  {String} reprompt THe reprompt message
 * @return {String} The rendered string to send back to Alexa
 */
DefaultResponseManager.prototype.ask = function(msg, reprompt) {
	return this._askResponse.render(
		{
			'msg' : msg,
			'reprompt' : reprompt
		}
	);
};

/**
 * Helper method to do an ask similar to the alexa api
 * @param  {String} msg      The message to tell to the user
 * @return {String} The rendered string to send back to Alexa
 */
DefaultResponseManager.prototype.tell = function(msg) {
	return this._tellResponse.render(
		{'msg' : msg}
	);
};

module.exports = DefaultResponseManager;