'use strict';

/*
 *+------------------------------------------------------------------------+
 *| Licensed Materials - Property of IBM
 *| IBM Cognos Products: Dashboard
 *| (C) Copyright IBM Corp. 2017 - 2020
 *|
 *| US Government Users Restricted Rights - Use, duplication or disclosure
 *| restricted by GSA ADP Schedule Contract with IBM Corp.
 *+------------------------------------------------------------------------+
 */
define(['../../../lib/@waca/core-client/js/core-client/ui/core/Class', '../SourceModelAPI', '../../models/sources/SourceModel', './EmbeddedModuleManager'], function (Class, SourceModelAPI, SourceModel, EmbeddedModuleManager) {
	'use strict';

	var SourcesCollectionManager = Class.extend({
		init: function init(options) {
			SourcesCollectionManager.inherited('init', this, arguments);
			this.sourcesCollection = options.sourcesCollection;
			this.dashboardApi = options.dashboardApi;

			this._sourceModelAPIs = {};

			//Session usage state
			this.widgetSources = {};
			this.sourceUsage = {};
		},

		/**
   * Returns a sourceAPI object for the given id
   * @param  {String} id the id of the source
   * @return {Object} sourceAPI object
   */
		getSource: function getSource(id) {
			if (!this._sourceModelAPIs[id]) {
				var sourceModel = this.sourcesCollection.get(id);
				if (!sourceModel) {
					return null;
				}

				this._sourceModelAPIs[id] = new SourceModelAPI({
					sourceModel: sourceModel,
					dashboardApi: this.dashboardApi,
					sourcesCollectionManager: this
				});
			}

			return this._sourceModelAPIs[id];
		},

		/**
   * Returns all the sources with a certain assetId
   * @param  {String} assetId
   * @return {[SourceModel]}
   */
		getSourceModelsByAssetId: function getSourceModelsByAssetId(assetId) {
			var models = this.sourcesCollection.getModels();
			var sources = [];
			for (var i = 0; i < models.length; i++) {
				if (models[i].get('assetId') === assetId) {
					sources.push(models[i]);
				}
			}

			return sources;
		},

		/**
   * Returns the list of sourceId that match a given assetId.  This is needed since we can have multiple sources that point to the same assetId.
   * These sources should still talk to each via events.
   * @param  {String} assetId
   * @return {[String]}  The sourceIds
   */
		getSourceIdsFromAssetId: function getSourceIdsFromAssetId(assetId) {
			var models = this.sourcesCollection.getModels();
			var sourceIds = [];
			for (var i = 0; i < models.length; i++) {
				if (models[i].get('assetId') === assetId) {
					sourceIds.push(models[i].id);
				}
			}

			return sourceIds;
		},

		/**
   * Returns an array of sourceAPI objects
   * @return {Array} array of sourceAPI objects
   */
		getSources: function getSources() {
			var _this = this;

			var sources = [];
			var models = this.sourcesCollection.getModels();
			if (models) {
				models.forEach(function (model) {
					sources.push(_this.getSource(model.get('id')));
				});
			}
			return sources;
		},

		/**
   * Remove a source model from the collection.
   * @param {String} id The id of the source to remove
   * @param {object} options These options will be passed to the collection remove method.  Look at Collection.js for description.
   */
		removeSource: function removeSource(id, options) {
			if (this.isSourceUsed(id)) {
				return; //Do not allow the removal of a source that is in use.
			}

			var source = this.sourcesCollection.get(id);
			if (source) {
				if (source.shaping) {
					EmbeddedModuleManager.deleteEmbeddedModule(source.shaping, {
						ajaxSvc: this.dashboardApi.getGlassCoreSvc('.Ajax'),
						logger: this.logger
					});
					source.shaping.destroy();
				}
				this.sourcesCollection.remove(source, options);
				delete this._sourceModelAPIs[id];
			}
		},

		/**
   * Register a source as being used by the specified widget. If any other source was previously registered, remove that registration first.
   *
   * @param {String} widgetId   The id of the widget.
   * @param {String} sourceId   The id of the data source
   */
		registerUsage: function registerUsage(widgetId, sourceId) {
			if (this.widgetSources[widgetId]) {
				this.sourceUsage[this.widgetSources[widgetId]]--;
			}
			this.widgetSources[widgetId] = sourceId;
			if (!this.sourceUsage[sourceId]) {
				this.sourceUsage[sourceId] = 1;
			} else {
				this.sourceUsage[sourceId]++;
			}
		},

		/**
   * De-register any source used by the specified widget.
   *
   * @param {String} widgetId   The id of the widget.
   */
		deregisterUsage: function deregisterUsage(widgetId) {
			if (this.widgetSources[widgetId]) {
				this.sourceUsage[this.widgetSources[widgetId]]--;
				delete this.widgetSources[widgetId];
			}
		},

		/**
   * Check if a source is currently being used.
   * @param {String} sourceId   The id of the data source
   * @returns {Boolean}   True if the source is used.
   */
		isSourceUsed: function isSourceUsed(sourceId) {
			return this.sourceUsage[sourceId] > 0;
		},

		/**
   * Retrieve the id of the source being used by a widget.
   * @param {String} widgetId   The id of the widget.
   * @returns {String}   The id of the source used by the widget, if any.
   */
		usesSource: function usesSource(widgetId) {
			return this.widgetSources[widgetId];
		},

		/**
   * Adds the needed sources for the pin being added to the dashboard
   * @param  {Object} modelFragmentSpec the modelFragment from the dropped pin
   * @param  {Object} options contains the payload
   * @return {Object} Returns a map of sourceIDs pinnedSourceId to existingSourceId
   */
		addSourcesForPin: function addSourcesForPin(modelFragmentSpec, options) {
			var _this2 = this;

			var pinnedSources = modelFragmentSpec.dataSources ? modelFragmentSpec.dataSources.sources : [];
			var pinnedSourceIdMap = {};
			pinnedSources.forEach(function (pinnedSource) {
				var pinnedAssetId = pinnedSource.assetId;
				var existingSources = _this2.getSourceModelsByAssetId(pinnedAssetId);
				var newSourceModel = null;
				var shapingId = pinnedSource.shaping ? pinnedSource.shaping.shapingId : undefined;

				// Get rid of all traces of the embedded module so that we use the moserJSON in the spec
				if (pinnedSource.shaping) {
					delete pinnedSource.shaping.embeddedModuleId;
					delete pinnedSource.shaping.embeddedModuleName;
					// In a copy paste or a pin scenario, we are guaranteed to be in authoring mode.
					// However, an API user may be doing an addContent from consumption mode as custom apps do not have this notion.
					// Ensures we hit case #4 in ShapingModelManager meaning the shaping model gets loaded.
					pinnedSource.shaping.embeddedModuleUpToDate = false;
				}

				// If there's no existing source with the same assetId simply add the pinned one as a new source
				if (existingSources.length === 0) {
					// Keep track of the source dashboard name of where the pin came from in the source has shaping
					if (shapingId) {
						pinnedSource.pinSourceName = modelFragmentSpec.sourceName;
					}

					newSourceModel = new SourceModel(pinnedSource);
					_this2.sourcesCollection.add(newSourceModel, options);
				} else {
					var matchingSource = null;
					for (var i = 0; i < existingSources.length; i++) {
						var existingSource = existingSources[i];
						var existingSourceShapingId = existingSource.shaping ? existingSource.shaping.shapingId : undefined;

						// Only link the pin to an existing source if they both have the same shapingId
						if (shapingId === existingSourceShapingId) {
							matchingSource = existingSource;
							break;
						}
					}

					if (matchingSource) {
						pinnedSourceIdMap[pinnedSource.id] = matchingSource.id;
					} else {
						var pinnedSourceInitialId = pinnedSource.id;

						// Delete the pinned source ID so a new gets generated
						pinnedSource.id = undefined;

						// Keep track of the source dashboard name of where the pin came from
						pinnedSource.pinSourceName = modelFragmentSpec.sourceName;

						newSourceModel = new SourceModel(pinnedSource);
						_this2.sourcesCollection.add(newSourceModel, options);
						pinnedSourceIdMap[pinnedSourceInitialId] = newSourceModel.id;
					}
				}
			});

			return pinnedSourceIdMap;
		}
	});

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