'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/View', '../../../widgets/livewidget/nls/StringResources', './ConditionalPalettePicker', 'jquery', 'underscore', 'rave', '../../../lib/@waca/dashboard-common/dist/utils/Rave2RenderHelper', 'text!./templates/HistogramView.html', '../../../widgets/livewidget/query/VisQueryBuilder', '../../../DynamicFileLoader'], function (BaseView, resources, ConditionalPalettePicker, $, _, Rave2, Rave2RenderHelper, template, QueryBuilder, DynamicFileLoader) {
	'use strict';

	var HistogramView = BaseView.extend({
		templateString: template,
		_isRendering: false,

		init: function init() {
			var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};

			HistogramView.inherited('init', this, arguments);
			this.visualization = options.visualization;
			this.data = this._getConditionalData(this.visualization.getSlots().getMappedSlotList(), options.data);
			this.visModel = options.visModel;
			this.heatDataItem = this.visualization.getSlots().getSlot('heat').getDataItemList()[0];
			this.visQueryBuilder = new QueryBuilder({ 'visAPI': options.visModel });
			this.icons = options.icons;

			this._renderHelper = new Rave2RenderHelper({
				'raveView': this
			});

			this.$el.addClass('conditionalFormatView');
		},

		render: function render(options) {
			var _this = this;

			// If already rendering, don't start a new one as this
			// will mess up the conditional picker render process.
			if (this._isRendering) {
				return;
			}
			this._isRendering = true;

			// show borders (selected) by default
			options = options || {
				select: true
			};

			return this.visModel.getConditionalMinMaxValue().then(function (data) {
				_this._setMinMax(data.min, data.max);
				return _this._initHistogram(options).then(function (rave2Vis) {
					var coordinates = this._renderHistogram(rave2Vis);
					return this._renderConditionalPicker(coordinates);
				}.bind(_this));
			}).catch(function (error) {
				_this._isRendering = false;
				return Promise.reject(error);
			});
		},

		remove: function remove() {
			if (this.palettePicker) {
				this.palettePicker.remove();
			}
			this.visQueryBuilder = null;
			this._renderHelper = null;
			this.$el && this.$el.parent() && this.$el.parent().off('mousedown.histogramView dragstart.histogramView touchstart.histogramView touchmove.histogramView');
			HistogramView.inherited('remove', this, arguments);
		},

		_setMinMax: function _setMinMax(min, max) {
			var palette = this._getConditionalPalette();
			if (palette) {
				var paletteSize = palette.getSize();

				if (paletteSize > 0) {
					this.min = Math.min(min, palette.getColor(0).getValue());
					this.max = Math.max(max, palette.getColor(paletteSize - 1).getValue());
				} else {
					this.min = min;
					this.max = max;
				}

				this.min = Math.floor(this.min);
				this.max = Math.ceil(this.max);
			}
		},

		refresh: function refresh(options) {
			options = options || {};

			if (!options.force && (this.width !== this.$el.width() || this._hasPaletteColorCountChanged())) {
				options.force = true;
			}

			if (options.force || options.data) {
				if (options.data) {
					this.data = this._getConditionalData(this.visualization.getSlots().getMappedSlotList(), options.data);
				}
				if (options.force || this._dataChanged) {
					this.$el.empty();
					return this.render(options);
				} else {
					return Promise.resolve(this);
				}
			}

			// toggle the borders based on the selection
			this._toggleBorders(options.select);

			return Promise.resolve(this);
		},

		_hasPaletteColorCountChanged: function _hasPaletteColorCountChanged() {
			if (this.palettePicker && this.palettePicker.slider && this.visModel) {
				return this.palettePicker.slider.maxHandles !== this.visModel.getConditionalPaletteLength() + 1;
			}
			return false;
		},


		getVisModel: function getVisModel() {
			return this.visModel;
		},

		_toggleBorders: function _toggleBorders(show) {
			if (show) {
				this.$el.find('.border').show();
			} else {
				this.$el.find('.border').hide();
			}
		},

		_getConditionalData: function _getConditionalData(mappings, data) {
			var _this2 = this;

			this._dataChanged = false;
			var index = -1,
			    heatDataItemIndex = void 0,
			    rankColumnCount = 0;

			// consider the data has changed
			var dataObj = data.getResult();
			var dataRowSize = dataObj.getRowCount();
			if (!this.data || dataRowSize !== this.data.length) {
				this._dataChanged = true;
			}

			// find the heat data item index
			// slot prior to the heat slot may contain more than one dataitems
			_.each(mappings, function (mapping) {
				if (mapping.getId() === 'heat') {
					heatDataItemIndex = ++index;
				} else if (mapping.getDefinition().getProperty('repeats')) {
					//the query response for repeating slots will have a data point for every data item in the slot
					index += mapping.getDataItemList().length;
				} else {
					index++;
				}
				rankColumnCount += _this2._getRankColumnCount(mapping);
			});

			// need to add the count of the rank columns to the heatDataItemIndex
			heatDataItemIndex += rankColumnCount;

			// extract the conditional values
			var result = [];
			if (heatDataItemIndex > -1) {
				for (var i = 0; i < dataRowSize; i++) {
					var dataCell = dataObj.getValue(i, heatDataItemIndex);
					if (!this._dataChanged && this.data) {
						// check whether the data has changed
						this._dataChanged = dataCell.value !== this.data[i];
					}
					result.push(dataCell.value);
				}
			}
			return result;
		},

		_getRankColumnCount: function _getRankColumnCount(mapping) {
			var rankColumnCount = 0;
			var dataItemAPIs = mapping.getDataItemList();
			_.each(dataItemAPIs, function (dataItem) {
				var topBottomInfo = dataItem.getTopBottom();
				if (topBottomInfo && topBottomInfo.rank) {
					rankColumnCount++;
				}
			});
			return rankColumnCount;
		},


		_getConditionalMapping: function _getConditionalMapping(mapping) {
			return _.find(mapping, function (m) {
				return m.getId() === 'heat';
			});
		},

		_shapeHistogramData: function _shapeHistogramData() {
			var max_buckets = 10;
			var histogramData = [];
			var delta = (this.max - this.min) / max_buckets;

			// init with zero
			for (var i = 0; i < max_buckets; i++) {
				histogramData[i] = [String(i * delta), 0];
			}

			_.each(this.data, function (row) {
				if (row !== undefined && row !== null) {
					var index = Math.min(max_buckets - 1, Math.floor((row - this.min) / delta));
					index = index < 0 ? 0 : index;
					histogramData[index][1]++;
				}
			}.bind(this));

			return histogramData;
		},

		_setHistogramProps: function _setHistogramProps(rave2Vis) {
			var props = [
			// x axis props
			{
				name: 'axis.x.title.display',
				value: false
			}, {
				name: 'axis.x.line.display',
				value: false
			}, {
				name: 'axis.x.labels.display',
				value: false
			}, {
				name: 'axis.x.gridlines.display',
				value: false
			}, {
				name: 'axis.x.scale.includeZero',
				value: true
			},
			// y axis props
			{
				name: 'axis.y.title.display',
				value: true
			}, {
				name: 'axis.y.line.display',
				value: false
			}, {
				name: 'axis.y.labels.display',
				value: false
			}, {
				name: 'axis.y.gridlines.display',
				value: true
			}, {
				name: 'axis.y.scale.includeZero',
				value: true
			}, {
				name: 'axis.y.title.text',
				value: resources.get('HistogramYAxisTitle')
			}, {
				name: 'axis.y.title.style.font-size',
				value: '11px'
			},
			// layout props
			{
				name: 'layout.axissize.left.preferred',
				value: '0'
			}, {
				name: 'layout.axissize.left.min',
				value: '0'
			}, {
				name: 'layout.axissize.bottom.preferred',
				value: '0'
			}, {
				name: 'layout.axissize.bottom.min',
				value: '0'
			}, {
				name: 'layout.legendsize.preferred',
				value: '0'
			}, {
				name: 'layout.legendsize.min',
				value: '0'
			}, {
				name: 'layout.padding',
				value: '0'
			}, {
				name: 'layout.chart.padding.top',
				value: '0'
			}, {
				name: 'layout.chart.padding.left',
				value: '0'
			}, {
				name: 'layout.chart.padding.bottom',
				value: '1'
			}, {
				name: 'layout.chart.padding.right',
				value: '0'
			},
			// legend props
			{
				name: 'legend.display',
				value: false
			},
			// line props
			{
				name: 'lineWithPoints.interpolate',
				value: 'basis'
			}, {
				name: 'lineWithPoints.display',
				value: 'line'
			}];
			_.each(props, function (prop) {
				rave2Vis.property(prop.name, prop.value);
			}.bind(this));
		},

		_initCanvas: function _initCanvas(options) {
			this.$el.empty();

			options.title = resources.get('conditionalPalettePickerLabel', {
				title: this.heatDataItem.getLabel()
			});

			this.$el.append(this.dotTemplate(options));
			this.$el.parent().on('mousedown.histogramView dragstart.histogramView touchstart.histogramView touchmove.histogramView', function (event) {
				$('.popover').popover('hide');
				event.stopPropagation();
				event.preventDefault(); // Stops the widget from moving when in authoring mode
			});

			this.width = this.$el.width();
		},

		_initHistogram: function _initHistogram(options) {
			var _this3 = this;

			return DynamicFileLoader.load(['rave-library-line']).then(function (modules) {
				var Bundle = modules[0];
				_this3._rave2Vis = Bundle.create('line');
				_this3._visDataModel = _this3._rave2Vis.createDataModel(_this3._renderHelper.getDefaultDataModel().id());
				_this3._disableRaveActions(_this3._rave2Vis);
				_this3._setHistogramProps(_this3._rave2Vis);
				_this3._initCanvas(options);

				return _this3._rave2Vis;
			});
		},

		_renderHistogram: function _renderHistogram(rave2Vis) {
			var statsData = this._shapeHistogramData();

			// Create a dataset with the conditional measure stats
			var dataSet = this._renderHelper.getRAVE2DataSet();
			dataSet.data(statsData);

			dataSet.slot('x').push().type('string').accessor(function (dataRow) {
				return dataRow[0];
			});
			dataSet.slot('y').push().type('numeric').accessor(function (dataRow) {
				return dataRow[1];
			});

			rave2Vis.node(Rave2.select(this.$el[0]).append('svg:svg').attr('class', 'rave-svg histogram-svg'));
			rave2Vis.render();

			return this._calculateHistogramCoordinate();
		},

		/**
   * Parse the SVG path to determine the histogram coordinates
   *
   * Example of SVG path string
   * "M80.9,79.13834373316936L98.9,77.16140102203092 ... L1052.9,79.13834373316936"
   */

		_getHistogramChartElement: function _getHistogramChartElement() {
			return this.$el.find('.element-shape');
		},

		_calculateHistogramCoordinate: function _calculateHistogramCoordinate() {
			var element = this._getHistogramChartElement();
			if (element.length > 0) {
				var directions = element.attr('d');
				if (directions) {
					var coordinates = directions.split(/[CML]+/);
					// skip the first empty coordinate (empty split by starting 'M')
					var start = coordinates[1].split(',');
					var end = coordinates[coordinates.length - 1].split(',');

					return {
						x1: parseFloat(start[0]),
						y1: parseFloat(start[1]),
						x2: parseFloat(end[0]),
						y2: parseFloat(end[1])
					};
				}
			}
			return { x1: 0, y1: 0, x2: 0, y2: 0 };
		},

		_disableRaveActions: function _disableRaveActions(rave2Vis) {
			rave2Vis.action('highlight').autoBind(false);
			rave2Vis.action('unhighlight').autoBind(false);
			rave2Vis.action('toggleSelect').autoBind(false);
			rave2Vis.action('zoom').autoBind(false);
		},

		_conditionalPickerCallback: function _conditionalPickerCallback() {
			this.refresh({
				force: true
			});
		},

		_renderConditionalPicker: function _renderConditionalPicker(c) {
			var _this4 = this;

			if (this.palettePicker) {
				this.palettePicker.min = this.min;
				this.palettePicker.max = this.max;
			} else {
				this.palettePicker = new ConditionalPalettePicker({
					el: this.el,
					min: this.min,
					max: this.max,
					palette: this._getConditionalPalette(),
					format: this.heatDataItem.getFormat(),
					widget: this.visModel.ownerWidget,
					visModel: this.visModel,
					icons: this.icons,
					callback: this._conditionalPickerCallback.bind(this)
				});
			}
			return this.palettePicker.render(c).then(function () {
				_this4._isRendering = false;
			});
		},

		_getConditionalPalette: function _getConditionalPalette() {
			var conditions = this.visModel.getConditions();
			return conditions ? conditions.palette : null;
		}
	});

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