<commit_before>'use strict';
const fs = require("fs");
const async = require("async");
const hash = require('object-hash');
const formidable = require('formidable');

const utils = require("../../../utils/utils.js");
const helper = require("./helper.js");
let colName = "infra";

function checkIfError(soajs, mainCb, data, cb) {
	utils.checkErrorReturn(soajs, mainCb, data, cb);
}

function validateId(soajs, cb) {
	BL.model.validateId(soajs, cb);
}

function initBLModel(BLModule, modelName, cb) {
	BLModule.init(modelName, cb);
}

var BL = {
	model: null,
	
	/**
	 * List Infra Providers
	 *
	 * @param {Object} config
	 * @param {Object} SOAJS
	 * @param {Drivers} Deployer
	 * @param {Callback} cbMain
	 */
	"list": function (config, soajs, deployer, cbMain) {
		let opts = {
			collection: colName
		};
		
		if (soajs.inputmaskData.envCode) {
			opts.conditions = {"deployments.environments": {"$in": [soajs.inputmaskData.envCode.toUpperCase()]}};
		}
		
		if (soajs.inputmaskData.technology) {
			opts.conditions = {"deployments.technology": soajs.inputmaskData.technology};
		}
		
		BL.model.findEntries(soajs, opts, function (err, records) {
			checkIfError(soajs, cbMain, {config: config, error: err, code: 600}, function () {
				
				//todo: call the drivers to get the regions for each provider before returning the response
				async.each(records, (oneInfra, mCb) => {
					
					let options = {
						soajs: soajs,
						env: process.env.SOAJS_ENV.toLowerCase(),
						model: BL.model
					};
					options.infra = oneInfra;
					
					async.series({
						"getRegions": (vCb) => {
							//get resion api info by calling deployer
							deployer.execute({
								'type': 'infra',
								'driver': oneInfra.name,
								'technology': 'cluster'
							}, 'getRegions', options, (error, regions) => {
								checkIfError(soajs, vCb, {config: config, error: error, code: 600}, function () {
									oneInfra.regions = regions.regions;
									oneInfra.templatesTypes = oneInfra.templates;
									return vCb();
								});
							});
						},
						"getLocalTemplates": (vCb) => {
							if (!oneInfra.templatesTypes || oneInfra.templatesTypes.indexOf('local') === -1) {
								return vCb();
							}
							
							oneInfra.templates = [];
							let opts = {
								collection: "templates",
								conditions: {
									"type": "_infra",
									"infra": oneInfra._id.toString()
								}
							};
							BL.model.findEntries(soajs, opts, function (error, records) {
								checkIfError(soajs, vCb, {config: config, error: error, code: 600}, function () {
									oneInfra.templates = records;
									return vCb();
								});
							});
						},
						"getRemoteTemplates": (vCb) => {
							if (!oneInfra.templatesTypes || oneInfra.templatesTypes.indexOf('external') === -1) {
								return vCb();
							}
							oneInfra.templates = [];
							//get resion api info by calling deployer
							deployer.execute({
								'type': 'infra',
								'driver': oneInfra.name,
								'technology': 'cluster'
							}, 'getFiles', options, (error, templates) => {
								checkIfError(soajs, vCb, {config: config, error: error, code: 600}, function () {
									if(!templates || templates.length === 0){
										return vCb();
									}
									
									let templateInputs = {};
									async.eachSeries(templates, (oneTemplate, fCb) => {
										if (oneTemplate.tags && oneTemplate.tags.type === 'inputsAndDisplay') {
											options.params = {id: oneTemplate.id};
											deployer.execute({
												'type': 'infra',
												'driver': oneInfra.name,
												'technology': 'cluster'
											}, 'downloadFile', options, (error, response) => {
												checkIfError(soajs, fCb, {
													config: config,
													error: error,
													code: 600
												}, function () {
													let tempFilePath = __dirname + oneTemplate.name + oneTemplate.id + ".json";
													let tempFile = fs.createWriteStream(tempFilePath, {"encoding": "utf8"});
													response.stream.pipe(tempFile);
													tempFile.on('error', (error) => {
														return fCb(error);
													});
													
													tempFile.on('finish', () => {
														try {
															let inputs = require(tempFilePath);
															templateInputs[oneTemplate.tags.template] = inputs;
														}
														catch (e) {
															soajs.log.error(e);
														}
														fs.unlinkSync(tempFilePath);
														return fCb();
													});
												});
											});
										}
										else {
											return fCb();
										}
									}, (error) => {
										checkIfError(soajs, vCb, {
											config: config,
											error: error,
											code: (error && error.code) ? error.code : 600
										}, () => {
											async.each(templates, (oneTemplate, fCb) => {
												if (oneTemplate.tags && oneTemplate.tags.type === 'template') {
													let myTemplate = {
														_id: oneTemplate.id,
														name: oneTemplate.name,
														description: oneTemplate.description,
														location: "external",
														tags: oneTemplate.tags
													};
													
													if(templateInputs && templateInputs[oneTemplate.id]){
														myTemplate.inputs = templateInputs[oneTemplate.id].inputs;
														myTemplate.display = templateInputs[oneTemplate.id].display;
													}
													
													oneInfra.templates.push(myTemplate);
												}
												return fCb();
											}, vCb);
										});
									});
								});
							});
						}
					}, mCb);
				}, (error) => {
					checkIfError(soajs, cbMain, {config: config, error: error, code: 600}, function () {
						return cbMain(null, records);
					});
				});
			});
		});
	},
	
	/**
	 * Connect new infra provider
	 * @param config
	 * @param soajs
	 * @param deployer
	 * @param cbMain<commit_msg>updated processing flow to ensure returned responses. switched from tag checking to type checking in the case of external templates.<commit_after>'use strict';
const fs = require("fs");
const async = require("async");
const hash = require('object-hash');
const formidable = require('formidable');

const utils = require("../../../utils/utils.js");
const helper = require("./helper.js");
let colName = "infra";

function checkIfError(soajs, mainCb, data, cb) {
	utils.checkErrorReturn(soajs, mainCb, data, cb);
}

function validateId(soajs, cb) {
	BL.model.validateId(soajs, cb);
}

function initBLModel(BLModule, modelName, cb) {
	BLModule.init(modelName, cb);
}

var BL = {
	model: null,
	
	/**
	 * List Infra Providers
	 *
	 * @param {Object} config
	 * @param {Object} SOAJS
	 * @param {Drivers} Deployer
	 * @param {Callback} cbMain
	 */
	"list": function (config, soajs, deployer, cbMain) {
		let opts = {
			collection: colName
		};
		
		if (soajs.inputmaskData.envCode) {
			opts.conditions = {"deployments.environments": {"$in": [soajs.inputmaskData.envCode.toUpperCase()]}};
		}
		
		if (soajs.inputmaskData.technology) {
			opts.conditions = {"deployments.technology": soajs.inputmaskData.technology};
		}
		
		BL.model.findEntries(soajs, opts, function (err, records) {
			checkIfError(soajs, cbMain, {config: config, error: err, code: 600}, function () {
				
				//todo: call the drivers to get the regions for each provider before returning the response
				async.mapSeries(records, (oneInfra, mCb) => {
					
					let options = {
						soajs: soajs,
						env: process.env.SOAJS_ENV.toLowerCase(),
						model: BL.model
					};
					options.infra = oneInfra;
					
					async.auto({
						"getRegions": (vCb) => {
							//get resion api info by calling deployer
							deployer.execute({
								'type': 'infra',
								'driver': oneInfra.name,
								'technology': 'cluster'
							}, 'getRegions', options, (error, regions) => {
								checkIfError(soajs, vCb, {config: config, error: error, code: 600}, function () {
									oneInfra.regions = regions.regions;
									oneInfra.templatesTypes = oneInfra.templates;
									return vCb();
								});
							});
						},
						"getLocalTemplates": ['getRegions', (info, vCb) => {
							if (!oneInfra.templatesTypes || oneInfra.templatesTypes.indexOf('local') === -1) {
								return vCb();
							}
							
							oneInfra.templates = [];
							let opts = {
								collection: "templates",
								conditions: {
									"type": "_infra",
									"infra": oneInfra._id.toString()
								}
							};
							BL.model.findEntries(soajs, opts, function (error, records) {
								checkIfError(soajs, vCb, {config: config, error: error, code: 600}, function () {
									oneInfra.templates = records;
									return vCb();
								});
							});
						}],
						"getRemoteTemplates": ['getRegions', (info, vCb) => {
							if (!oneInfra.templatesTypes || oneInfra.templatesTypes.indexOf('external') === -1) {
								return vCb();
							}
							
							oneInfra.templates = [];
							//get resion api info by calling deployer
							deployer.execute({
								'type': 'infra',
								'driver': oneInfra.name,
								'technology': 'cluster'
							}, 'getFiles', options, (error, templates) => {
								checkIfError(soajs, vCb, {config: config, error: error, code: 600}, function () {
									if(!templates || templates.length === 0){
										return vCb();
									}
									
									let templateInputs = {};
									async.each(templates, (oneTemplate, fCb) => {
										if (oneTemplate.type && oneTemplate.type === 'inputsAndDisplay') {
											options.params = {id: oneTemplate.id};
											deployer.execute({
												'type': 'infra',
												'driver': oneInfra.name,
												'technology': 'cluster'
											}, 'downloadFile', options, (error, response) => {
												checkIfError(soajs, fCb, {
													config: config,
													error: error,
													code: 600
												}, function () {
													let tempFilePath = __dirname + oneTemplate.name + oneTemplate.id;
													if(tempFilePath.indexOf(".json") === -1){
														tempFilePath += ".json";
													}
													
													let tempFile = fs.createWriteStream(tempFilePath, {"encoding": "utf8"});
													response.stream.pipe(tempFile);
													
													tempFile.on('error', (error) => {
														return fCb(error);
													});
													
													tempFile.on('close', () => {
														try {
															let inputs = require(tempFilePath);
															templateInputs[oneTemplate.tags.template] = inputs;
														}
														catch (e) {
															soajs.log.error(e);
														}
														//clean up
														fs.unlink(tempFilePath, (error) => {
															if(error){
																soajs.log.error(error);
															}
															return fCb();
														});
													});
												});
											});
										}
										else {
											return fCb();
										}
									}, (error) => {
										checkIfError(soajs, vCb, {
											config: config,
											error: error,
											code: (error && error.code) ? error.code : 600
										}, () => {
											async.each(templates, (oneTemplate, lCb) => {
												if (oneTemplate.type && oneTemplate.type === 'template') {
													let myTemplate = {
														_id: oneTemplate.id,
														name: oneTemplate.name,
														description: oneTemplate.description,
														location: "external",
														tags: oneTemplate.tags
													};
													
													if(templateInputs && templateInputs[oneTemplate.id]){
														myTemplate.inputs = templateInputs[oneTemplate.id].inputs;
														myTemplate.display = templateInputs[oneTemplate.id].display;
													}
													
													oneInfra.templates.push(myTemplate);
													
												}
												return lCb();
											}, vCb);
										});
									});
								});
							});
						}]
					}, mCb);
				}, (error) => {
					checkIfError(soajs, cbMain, {config: config, error: error, code: 600}, function () {
						return cbMain(null, records);
					});
				});
			});
		});
	},
	
	/**
	 * Connect new infra provider
	 * @param config
	 * @param soajs
	 * @param deployer
	 * @param cbMain
{'fraction_non_alphanumeric': 0.14224312707809586, 'fraction_numerical': 0.004135917606033574, 'mean_word_length': 1.8759328358208955, 'pattern_counts': {'":': 20, '<': 3, '<?xml version=': 0, '>': 32, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '481620', 'n_tokens_mistral': 6217, 'n_tokens_neox': 3697, 'n_words': 768}