/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

(function() {
	'use strict';

	var featureControllers = angular.module('featureControllers');
	var feature = featureControllers.register("metrics");

	// ==============================================================
	// =                       Initialization                       =
	// ==============================================================

	// ==============================================================
	// =                         Controller                         =
	// ==============================================================

	// ========================= Dashboard ==========================
	feature.navItem("dashboard", "Metrics", "line-chart");

	feature.controller('dashboard', function(PageConfig, $scope, $http, $q, UI, Site, Authorization, Application, Entities) {
		var _siteApp = Site.currentSiteApplication();
		var _druidConfig = _siteApp.configObj.druid;
		var _refreshInterval;

		var _menu_newChart;

		$scope.lock = false;

		$scope.dataSourceListReady = false;
		$scope.dataSourceList = [];
		$scope.dashboard = {
			groups: []
		};
		$scope.dashboardEntity = null;
		$scope.dashboardReady = false;

		$scope._newMetricFilter = "";
		$scope._newMetricDataSrc = null;
		$scope._newMetricDataMetric = null;

		$scope.tabHolder = {};

		$scope.endTime = app.time.now();
		$scope.startTime = $scope.endTime.clone();

		// =================== Initialization ===================
		if(!_druidConfig || !_druidConfig.coordinator || !_druidConfig.broker) {
			$.dialog({
				title: "OPS",
				content: "Druid configuration can't be empty!"
			});
			return;
		}

		$scope.autoRefreshList = [
			{title: "Last 1 Month", timeDes: "day", getStartTime: function(endTime) {return endTime.clone().subtract(1, "month");}},
			{title: "Last 1 Day", timeDes: "thirty_minute", getStartTime: function(endTime) {return endTime.clone().subtract(1, "day");}},
			{title: "Last 6 Hour", timeDes: "fifteen_minute", getStartTime: function(endTime) {return endTime.clone().subtract(6, "hour");}},
			{title: "Last 2 Hour", timeDes: "fifteen_minute", getStartTime: function(endTime) {return endTime.clone().subtract(2, "hour");}},
			{title: "Last 1 Hour", timeDes: "minute", getStartTime: function(endTime) {return endTime.clone().subtract(1, "hour");}}
		];
		$scope.autoRefreshSelect = $scope.autoRefreshList[2];

		// ====================== Function ======================
		$scope.setAuthRefresh = function(item) {
			$scope.autoRefreshSelect = item;
			$scope.chartRefresh(true);
		};

		$scope.refreshTimeDisplay = function() {
			PageConfig.pageSubTitle = common.format.date($scope.startTime) + " ~ " + common.format.date($scope.endTime) + " [refresh interval: 30s]";
		};
		$scope.refreshTimeDisplay();

		// ======================= Metric =======================
		// Fetch metric data
		$http.get(_druidConfig.coordinator + "/druid/coordinator/v1/metadata/datasources", {withCredentials: false}).then(function(data) {
			var _endTime = new moment();
			var _startTime = _endTime.clone().subtract(1, "day");
			var _intervals = _startTime.toISOString() + "/" + _endTime.toISOString();

			$scope.dataSourceList = $.map(data.data, function(dataSrc) {
				return {
					dataSource: dataSrc,
					metricList: []
				};
			});

			// List dataSource metrics
			var _metrixList_promiseList = $.map($scope.dataSourceList, function(dataSrc) {
				var _data = JSON.stringify({
					"queryType": "groupBy",
					"dataSource": dataSrc.dataSource,
					"granularity": "all",
					"dimensions": ["metric"],
					"aggregations": [
						{
							"type":"count",
							"name":"count"
						}
					],
					"intervals": [_intervals]
				});

				return $http.post(_druidConfig.broker + "/druid/v2", _data, {withCredentials: false}).then(function(response) {
					dataSrc.metricList = $.map(response.data, function(entity) {
						return entity.event.metric;
					});
				});
			});

			$q.all(_metrixList_promiseList).finally(function() {
				$scope.dataSourceListReady = true;

				$scope._newMetricDataSrc = $scope.dataSourceList[0];
				$scope._newMetricDataMetric = common.getValueByPath($scope._newMetricDataSrc, "metricList.0");
			});
		}, function() {
			$.dialog({
				title: "OPS",
				content: "Fetch data source failed. Please check Site Application Metrics configuration."
			});
		});

		// Filter data source
		$scope.dataSourceMetricList = function(dataSrc, filter) {
			filter = (filter || "").toLowerCase().trim().split(/\s+/);
			return $.grep((dataSrc && dataSrc.metricList) || [], function(metric) {
				for(var i = 0 ; i < filter.length ; i += 1) {
					if(metric.toLowerCase().indexOf(filter[i]) === -1) return false;
				}
				return true;
			});
		};

		// New metric select
		$scope.newMetricSelectDataSource = function(dataSrc) {
			if(dataSrc !== $scope._newMetricDataMetric) $scope._newMetricDataMetric = dataSrc.metricList[0];
			$scope._newMetricDataSrc = dataSrc;
		};
		$scope.newMetricSelectMetric = function(metric) {
			$scope._newMetricDataMetric = metric;
		};

		// Confirm new metric
		$scope.confirmSelectMetric = function() {
			var group = $scope.tabHolder.selectedPane.data;
			$("#metricMDL").modal('hide');

			group.charts.push({
				chart: "line",
				dataSource: $scope._newMetricDataSrc.dataSource,
				metric: $scope._newMetricDataMetric,
				aggregations: ["max"]
			});

			$scope.chartRefresh();
		};

		// ======================== Menu ========================
		$scope.newGroup = function() {
			if($scope.lock) return;

			UI.createConfirm("Group", {}, [{field: "name"}], function(entity) {
				if(common.array.find(entity.name, $scope.dashboard.groups, "name")) {
					return "Group name conflict";
				}
			}).then(null, null, function(holder) {
				$scope.dashboard.groups.push({
					name: holder.entity.name,
					charts: []
				});
				holder.closeFunc();

				setTimeout(function() {
					$scope.tabHolder.setSelect(holder.entity.name);
				}, 0);
			});
		}

		function deleteGroup() {
			var group = $scope.tabHolder.selectedPane.data;
			UI.deleteConfirm(group.name).then(null, null, function(holder) {
				common.array.remove(group, $scope.dashboard.groups);
				holder.closeFunc();
			});
		}

		_menu_newChart = {title: "Add Metric", func: function() {$scope.newChart();}};
		Object.defineProperties(_menu_newChart, {
			icon: {
				get: function() {return $scope.dataSourceListReady ? 'plus' : 'refresh fa-spin';}
			},
			disabled: {
				get: function() {return !$scope.dataSourceListReady;}
			}
		});

		$scope.menu = Authorization.isRole('ROLE_ADMIN') ? [
			{icon: "cog", title: "Configuration", list: [
				_menu_newChart,
				{icon: "trash", title: "Delete Group", danger: true, func: deleteGroup}
			]},
			{icon: "plus", title: "New Group", func: $scope.newGroup}
		] : [];

		// ===================== Dashboard ======================
		$scope.dashboardList = Entities.queryEntities("GenericResourceService", {
			site: Site.current().tags.site,
			application: Application.current().tags.application
		});
		$scope.dashboardList._promise.then(function(list) {
			$scope.dashboardEntity = list[0];
			$scope.dashboard = $scope.dashboardEntity ? common.parseJSON($scope.dashboardEntity.value) : {groups: []};
			$scope.chartRefresh();
		}).finally(function() {
			$scope.dashboardReady = true;
		});

		$scope.saveDashboard = function() {
			$scope.lock = true;

			if(!$scope.dashboardEntity) {
				$scope.dashboardEntity = {
					tags: {
						site: Site.current().tags.site,
						application: Application.current().tags.application,
						name: "/metric_dashboard/dashboard/default"
					}
				};
			}
			$scope.dashboardEntity.value = common.stringify($scope.dashboard);

			Entities.updateEntity("GenericResourceService", $scope.dashboardEntity)._promise.then(function() {
				$.dialog({
					title: "Done",
					content: "Save success!"
				});
			}, function() {
				$.dialog({
					title: "POS",
					content: "Save failed. Please retry."
				});
			}).finally(function() {
				$scope.lock = false;
			});
		};

		// ======================= Chart ========================
		$scope.configTargetChart = null;
		$scope.configPreviewChart = null;

		$scope.chartConfig = {
			xType: "time"
		};

		$scope.chartTypeList = [
			{icon: "line-chart", chart: "line"},
			{icon: "area-chart", chart: "area"},
			{icon: "bar-chart", chart: "column"},
			{icon: "pie-chart", chart: "pie"}
		];

		$scope.chartSeriesList = [
			{name: "Min", series: "min"},
			{name: "Max", series: "max"}
		];

		$scope.newChart = function() {
			$("#metricMDL").modal();
		};

		$scope.configPreviewChartMinimumCheck = function() {
			$scope.configPreviewChart.min = $scope.configPreviewChart.min === 0 ? undefined : 0;
			window.ccc1 = $scope.getChartConfig($scope.configPreviewChart);
		};

		$scope.seriesChecked = function(chart, series) {
			if(!chart) return false;
			return $.inArray(series, chart.aggregations || []) !== -1;
		};
		$scope.seriesCheckClick = function(chart, series) {
			if(!chart) return;
			if($scope.seriesChecked(chart, series)) {
				common.array.remove(series, chart.aggregations);
			} else {
				chart.aggregations.push(series);
			}
			$scope.chartSeriesUpdate(chart);
		};

		$scope.chartSeriesUpdate = function(chart) {
			chart._data = $.map(chart._oriData, function(series) {
				if($.inArray(series.key, chart.aggregations) !== -1) return series;
			});
		};

		$scope.getChartConfig = function(chart) {
			if(!chart) return null;

			var _config = chart._config = chart._config || $.extend({}, $scope.chartConfig);
			_config.yMin = chart.min;

			return _config;
		};

		$scope.configChart = function(chart) {
			$scope.configTargetChart = chart;
			$scope.configPreviewChart = $.extend({}, chart);
			delete $scope.configPreviewChart._config;
			$("#chartMDL").modal();
			setTimeout(function() {
				$(window).resize();
			}, 200);
		};

		$scope.confirmUpdateChart = function() {
			$("#chartMDL").modal('hide');
			common.extend($scope.configTargetChart, $scope.configPreviewChart);
			$scope.chartSeriesUpdate($scope.configTargetChart);
			if($scope.configTargetChart._holder) $scope.configTargetChart._holder.refreshAll();
		};

		$scope.deleteChart = function(group, chart) {
			UI.deleteConfirm(chart.metric).then(null, null, function(holder) {
				common.array.remove(chart, group.charts);
				holder.closeFunc();
				$scope.chartRefresh();
			});
		};

		$scope.chartRefresh = function(forceRefresh) {
			setTimeout(function() {
				$scope.endTime = app.time.now();
				$scope.startTime = $scope.autoRefreshSelect.getStartTime($scope.endTime);
				var _intervals = $scope.startTime.toISOString() + "/" + $scope.endTime.toISOString();

				$scope.refreshTimeDisplay();

				$.each($scope.dashboard.groups, function (i, group) {
					$.each(group.charts, function (j, chart) {
						var _data = JSON.stringify({
							"queryType": "groupBy",
							"dataSource": chart.dataSource,
							"granularity": $scope.autoRefreshSelect.timeDes,
							"dimensions": ["metric"],
							"filter": {"type": "selector", "dimension": "metric", "value": chart.metric},
							"aggregations": [
								{
									"type": "max",
									"name": "max",
									"fieldName": "maxValue"
								},
								{
									"type": "min",
									"name": "min",
									"fieldName": "maxValue"
								}
							],
							"intervals": [_intervals]
						});

						if (!chart._data || forceRefresh) {
							$http.post(_druidConfig.broker + "/druid/v2", _data, {withCredentials: false}).then(function (response) {
								chart._oriData = nvd3.convert.druid([response.data]);
								$scope.chartSeriesUpdate(chart);
								if(chart._holder) chart._holder.refresh();
							});
						} else {
							if(chart._holder) chart._holder.refresh();
						}
					});
				});
			}, 0);
		};

		_refreshInterval = setInterval(function() {
			if(!$scope.dashboardReady) return;
			$scope.chartRefresh(true);
		}, 1000 * 30);

		// ====================== Clean Up ======================
		$scope.$on('$destroy', function() {
			clearInterval(_refreshInterval);
		});
	});
})();