'use strict';

/**
 * Licensed Materials - Property of IBM
 * IBM Cognos Products: BI Cloud (C) Copyright IBM Corp. 2018, 2020
 * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
 */

define(['underscore', '../../../../lib/@waca/core-client/js/core-client/ui/core/Class', '../../nls/StringResources'], function (_, Class, resources) {

	'use strict';

	var VisKeyDriverExecution = Class.extend({

		// Different message types returned by the predict service.
		DIAG_MSG_TYPE: 'DIAG_MSG_TYPE',
		WARN_MSG_TYPE: 'WARN_MSG_TYPE',
		ERR_MSG_TYPE: 'ERR_MSG_TYPE',

		// MSG Type to logger title
		MSG_TO_LOG_TITLE: {
			DIAG_MSG_TYPE: 'FPD Diagnostics',
			WARN_MSG_TYPE: 'FPD Warnings',
			ERR_MSG_TYPE: 'FPD Errors'
		},

		/**
  * Predict service REST API response status values
  **/
		RESPONSE_STATUS: {
			'SUCCESS': 'SUCCESS'
		},

		/**
  * Predict service HTTP response status
  **/
		HTTP_RESPONSE_STATUS: {
			SUCCESS: 200,
			BAD_REQUEST: 400,
			SMARTS_SERVER_ERROR: 500
		},

		init: function init(options) {
			VisKeyDriverExecution.inherited('init', this, arguments);

			options = options || {};
			this.keyDriverService = options.keyDriverService;
			this.logger = options.logger;
		},

		_getConsoleFuncOutput: function _getConsoleFuncOutput(isError) {
			return isError ? console.error : console.warn;
		},


		/**
  * Log FPD service endpoint messages.
  * @param {String} messageType - see *_MSG_TYPE, where * is ERR, WARN or DIAG
  * @param {Boolean} isError - true if this is an error level set of message, false otherwise
  * @param {Array} messageArray - array of messages. This maybe and array of objects with
  * captions defined or may just be a string.
  */
		_logMessagesOfType: function _logMessagesOfType(messageType, isError, messageArray) {
			// Only log if we have messages
			if (messageArray && messageArray.length > 0) {
				// Determine the console and logger methods to use.
				var consoleFunc = this._getConsoleFuncOutput(isError); // put it in a method for testing purposes.
				var messageFunc = isError ? this.logger.error.bind(this.logger) : this.logger.warn.bind(this.logger);
				messageFunc && messageFunc(this.MSG_TO_LOG_TITLE[messageType]);
				try {
					consoleFunc && consoleFunc(this.MSG_TO_LOG_TITLE[messageType]);
				} catch (e) {/*IE11 will fail when you call consoleFunc() when the dev tools are closed.*/}
				messageArray.forEach(function (message) {
					// warnings and errors are objects with captions, diagnostics are just strings.
					var msg = message.caption ? message.caption : message;
					messageFunc && messageFunc(msg);
					try {
						consoleFunc && consoleFunc(msg);
					} catch (e) {/*IE11 will fail when you call consoleFunc() when the dev tools are closed.*/}
				});
			}
		},


		/**
   * @public
   * @function execute
   * Execute the SmartAnnotation query
   * @param {Object} Options
   * @returns a promise that resolves with an object with a result, error, and possibleDrivers.
   */
		execute: function execute(options /*targetId, assertId*/) {
			var _this = this;

			var querySpec = this._buildQuery(options);
			return this.keyDriverService.runQuery({
				querySpec: querySpec
			}).then(function (_ref) {
				var data = _ref.data;

				/*
    * What? The request is successful? Hurry, return the result while you can!
    * Ensure the result is what we expect and determine the possible drivers.
    */
				var possibleDrivers = [];
				var predictStatus = data.predictStatus;
				if (predictStatus && predictStatus.state !== 'SUCCESS') {
					/*
     We had a failure, lets log any reported diagnostics but we will also
     just carry on by returning empty possible key drivers. This will show the
     user a message and a blank vis. This can be improved upon in future releases.
     */
					_this._logMessagesOfType(_this.DIAG_MSG_TYPE, false /*isError */, predictStatus.diagnostics);
				} else if (data.results && data.results.recommendedFields && data.results.recommendedFields.fields) {
					// Success!!!, set the recommended drivers
					possibleDrivers = data.results.recommendedFields.fields;
				}
				/*
     Log warnings and errors.
    */
				_this._logMessagesOfType(_this.WARN_MSG_TYPE, false /*isError */, predictStatus.warnings);
				_this._logMessagesOfType(_this.ERR_MSG_TYPE, true /*isError */, predictStatus.errors);

				return {
					result: 'SUCCESS',
					error: null,
					possibleDrivers: possibleDrivers,
					fpdWarnings: predictStatus.warnings,
					fpdErrors: predictStatus.errors
				};
			}, function (err) {
				/*
    * Thats more like it, a failed call. Determine the error to return and build
    * an empty possibleDriver response.
    */
				return {
					result: 'ERROR',
					error: _this._errorResponseHandler(err),
					possibleDrivers: [],
					fpdWarnings: [],
					fpdErrors: []
				};
			});
		},

		_errorResponseHandler: function _errorResponseHandler(data) {
			var sMsg = void 0;
			var sFPDErrorMessage = void 0;
			var errorCategory = 'fpd_data_source_category';
			/*
    *Service Error response should always return a error code
    */
			var nErrCode = data && data.code ? data.code : 0;
			switch (nErrCode) {
				case this.HTTP_RESPONSE_STATUS.BAD_REQUEST:
					{
						sMsg = resources.get('smart_annotation_unauthorized');
						sFPDErrorMessage = resources.get('fpd_invalid_data_source');
						break;
					}
				case this.HTTP_RESPONSE_STATUS.SMARTS_SERVER_ERROR:
					{
						errorCategory = 'predict_error';
						sMsg = resources.get('smart_annotation_method');
						sFPDErrorMessage = resources.get('fpd_network_issue');
						break;
					}
				default:
					{
						sMsg = resources.get('smart_annotation_generic_error');
						sFPDErrorMessage = resources.get('fpd_invalid_data_source');
					}
			}
			var oErr = new Error();
			oErr.message = sMsg;
			oErr.code = data.code;
			oErr.stack = data.stack;
			oErr.caption = sFPDErrorMessage;
			oErr.categoryId = errorCategory;

			return oErr;
		},

		/**
   * @private
   * @function _buildSuggestionQuery
   * Build the suggestion query spec
   * @returns annotation suggestion query spec
   */
		_buildQuery: function _buildQuery(options) {
			var querySpec = {
				moduleId: options.assetId,
				targetFieldIDForExpression: options.targetId,
				tuningParams: {
					allowCategoryTarget: true,
					noCorrelationLimit: true
				},
				shapedModule: options.hasShaping
			};

			if (options.tempModule) {
				querySpec.tempModule = JSON.stringify(options.tempModule);
			}

			if (options.tempModuleId) {
				querySpec.tempModuleId = options.tempModuleId;
			}

			return querySpec;
		}
	});

	// Enum for the execution targets
	VisKeyDriverExecution.TARGETS = {
		SUGGESTIONS: 'suggestions',
		EXECUTIONS: 'executions'
	};

	return VisKeyDriverExecution;
});
//# sourceMappingURL=VisKeyDriverExecution.js.map