import $ from 'jquery';
import 'javascript-detect-element-resize/detect-element-resize';
import Subscription from '../api/subscription';
export default function WidgetController($scope, $timeout, $window, $element, $q, $log, $injector, $filter, tbRaf, types, utils, timeService,
datasourceService, deviceService, visibleRect, isEdit, stDiff, dashboardTimewindow,
dashboardTimewindowApi, widget, aliasesInfo, widgetType) {
var vm = this;
$scope.$timeout = $timeout;
$scope.$q = $q;
$scope.$injector = $injector;
$scope.tbRaf = tbRaf;
$scope.rpcRejection = null;
$scope.rpcErrorText = null;
$scope.rpcEnabled = false;
$scope.executingRpcRequest = false;
var gridsterItemInited = false;
var cafs = {};
var widgetContext = {
inited: false,
$scope: $scope,
$container: $('#container', $element),
$containerParent: $($element),
width: 0,
height: 0,
isEdit: isEdit,
isMobile: false,
widgetConfig: widget.config,
settings: widget.config.settings,
units: widget.config.units || '',
decimals: angular.isDefined(widget.config.decimals) ? widget.config.decimals : 2,
subscriptions: {},
defaultSubscription: null,
timewindowFunctions: {
onUpdateTimewindow: function(startTimeMs, endTimeMs) {
if (widgetContext.defaultSubscription) {
widgetContext.defaultSubscription.onUpdateTimewindow(startTimeMs, endTimeMs);
}
},
onResetTimewindow: function() {
if (widgetContext.defaultSubscription) {
widgetContext.defaultSubscription.onResetTimewindow();
}
}
},
subscriptionApi: {
createSubscription: function(options, subscribe) {
return createSubscription(options, subscribe);
},
createSubscriptionFromInfo: function (type, subscriptionsInfo, options, useDefaultComponents, subscribe) {
return createSubscriptionFromInfo(type, subscriptionsInfo, options, useDefaultComponents, subscribe);
},
removeSubscription: function(id) {
var subscription = widgetContext.subscriptions[id];
if (subscription) {
subscription.destroy();
delete widgetContext.subscriptions[id];
}
}
},
controlApi: {
sendOneWayCommand: function(method, params, timeout) {
if (widgetContext.defaultSubscription) {
return widgetContext.defaultSubscription.sendOneWayCommand(method, params, timeout);
}
return null;
},
sendTwoWayCommand: function(method, params, timeout) {
if (widgetContext.defaultSubscription) {
return widgetContext.defaultSubscription.sendTwoWayCommand(method, params, timeout);
}
return null;
}
},
utils: {
formatValue: formatValue
}
};
var subscriptionContext = {
$scope: $scope,
$q: $q,
$filter: $filter,
$timeout: $timeout,
tbRaf: tbRaf,
timeService: timeService,
deviceService: deviceService,
datasourceService: datasourceService,
utils: utils,
widgetUtils: widgetContext.utils,
dashboardTimewindowApi: dashboardTimewindowApi,
types: types,
stDiff: stDiff,
aliasesInfo: aliasesInfo
};
var widgetTypeInstance;
vm.useCustomDatasources = false;
try {
widgetTypeInstance = new widgetType(widgetContext);
} catch (e) {
handleWidgetException(e);
widgetTypeInstance = {};
}
if (!widgetTypeInstance.onInit) {
widgetTypeInstance.onInit = function() {};
}
if (!widgetTypeInstance.onDataUpdated) {
widgetTypeInstance.onDataUpdated = function() {};
}
if (!widgetTypeInstance.onResize) {
widgetTypeInstance.onResize = function() {};
}
if (!widgetTypeInstance.onEditModeChanged) {
widgetTypeInstance.onEditModeChanged = function() {};
}
if (!widgetTypeInstance.onMobileModeChanged) {
widgetTypeInstance.onMobileModeChanged = function() {};
}
if (!widgetTypeInstance.onDestroy) {
widgetTypeInstance.onDestroy = function() {};
}
if (widgetTypeInstance.useCustomDatasources) {
vm.useCustomDatasources = widgetTypeInstance.useCustomDatasources();
}
$scope.clearRpcError = function() {
if (widgetContext.defaultSubscription) {
widgetContext.defaultSubscription.clearRpcError();
}
}
vm.gridsterItemInitialized = gridsterItemInitialized;
initialize();
function createSubscriptionFromInfo(type, subscriptionsInfo, options, useDefaultComponents, subscribe) {
var deferred = $q.defer();
options.type = type;
if (useDefaultComponents) {
defaultComponentsOptions(options);
} else {
if (!options.timeWindowConfig) {
options.useDashboardTimewindow = true;
}
}
utils.createDatasoucesFromSubscriptionsInfo(subscriptionsInfo).then(
function (datasources) {
options.datasources = datasources;
var subscription = createSubscription(options, subscribe);
if (useDefaultComponents) {
defaultSubscriptionOptions(subscription, options);
}
deferred.resolve(subscription);
}
);
return deferred.promise;
}
function createSubscription(options, subscribe) {
options.dashboardTimewindow = dashboardTimewindow;
var subscription =
new Subscription(subscriptionContext, options);
widgetContext.subscriptions[subscription.id] = subscription;
if (subscribe) {
subscription.subscribe();
}
return subscription;
}
function defaultComponentsOptions(options) {
options.useDashboardTimewindow = angular.isDefined(widget.config.useDashboardTimewindow)
? widget.config.useDashboardTimewindow : true;
options.timeWindowConfig = options.useDashboardTimewindow ? dashboardTimewindow : widget.config.timewindow;
options.legendConfig = null;
if ($scope.displayLegend) {
options.legendConfig = $scope.legendConfig;
}
options.decimals = widgetContext.decimals;
options.units = widgetContext.units;
options.callbacks = {
onDataUpdated: function() {
widgetTypeInstance.onDataUpdated();
},
onDataUpdateError: function(subscription, e) {
handleWidgetException(e);
},
dataLoading: function(subscription) {
if ($scope.loadingData !== subscription.loadingData) {
$scope.loadingData = subscription.loadingData;
}
},
legendDataUpdated: function(subscription, apply) {
if (apply) {
$scope.$digest();
}
},
timeWindowUpdated: function(subscription, timeWindowConfig) {
widget.config.timewindow = timeWindowConfig;
$scope.$apply();
}
}
}
function defaultSubscriptionOptions(subscription, options) {
if (!options.useDashboardTimewindow) {
$scope.$watch(function () {
return widget.config.timewindow;
}, function (newTimewindow, prevTimewindow) {
if (!angular.equals(newTimewindow, prevTimewindow)) {
subscription.updateTimewindowConfig(widget.config.timewindow);
}
});
}
if ($scope.displayLegend) {
$scope.legendData = subscription.legendData;
}
}
function createDefaultSubscription() {
var subscription;
var options;
if (widget.type !== types.widgetType.rpc.value && widget.type !== types.widgetType.static.value) {
options = {
type: widget.type,
datasources: angular.copy(widget.config.datasources)
};
defaultComponentsOptions(options);
subscription = createSubscription(options);
defaultSubscriptionOptions(subscription, options);
widgetContext.datasources = subscription.datasources;
widgetContext.data = subscription.data;
widgetContext.hiddenData = subscription.hiddenData;
widgetContext.timeWindow = subscription.timeWindow;
} else if (widget.type === types.widgetType.rpc.value) {
$scope.loadingData = false;
options = {
type: widget.type,
targetDeviceAliasIds: widget.config.targetDeviceAliasIds
}
options.callbacks = {
rpcStateChanged: function(subscription) {
$scope.rpcEnabled = subscription.rpcEnabled;
$scope.executingRpcRequest = subscription.executingRpcRequest;
},
onRpcSuccess: function(subscription) {
$scope.executingRpcRequest = subscription.executingRpcRequest;
},
onRpcFailed: function(subscription) {
$scope.executingRpcRequest = subscription.executingRpcRequest;
$scope.rpcErrorText = subscription.rpcErrorText;
$scope.rpcRejection = subscription.rpcRejection;
},
onRpcErrorCleared: function() {
$scope.rpcErrorText = null;
$scope.rpcRejection = null;
}
}
subscription = createSubscription(options);
} else if (widget.type === types.widgetType.static.value) {
$scope.loadingData = false;
}
if (subscription) {
widgetContext.defaultSubscription = subscription;
}
}
function initialize() {
if (!vm.useCustomDatasources) {
createDefaultSubscription();
} else {
$scope.loadingData = false;
}
$scope.$on('toggleDashboardEditMode', function (event, isEdit) {
onEditModeChanged(isEdit);
});
addResizeListener(widgetContext.$containerParent[0], onResize);
$scope.$watch(function () {
return widget.row + ',' + widget.col + ',' + widget.config.mobileOrder;
}, function () {
$scope.$emit("widgetPositionChanged", widget);
});
$scope.$on('gridster-item-resized', function (event, item) {
if (!widgetContext.isMobile) {
widget.sizeX = item.sizeX;
widget.sizeY = item.sizeY;
}
});
$scope.$on('mobileModeChanged', function (event, newIsMobile) {
onMobileModeChanged(newIsMobile);
});
$scope.$on("$destroy", function () {
removeResizeListener(widgetContext.$containerParent[0], onResize);
onDestroy();
});
}
function handleWidgetException(e) {
$log.error(e);
$scope.widgetErrorData = utils.processWidgetException(e);
}
function onInit() {
if (!widgetContext.inited) {
widgetContext.inited = true;
try {
widgetTypeInstance.onInit();
} catch (e) {
handleWidgetException(e);
}
if (!vm.useCustomDatasources && widgetContext.defaultSubscription) {
widgetContext.defaultSubscription.subscribe();
}
}
}
function checkSize() {
var width = widgetContext.$containerParent.width();
var height = widgetContext.$containerParent.height();
var sizeChanged = false;
if (!widgetContext.width || widgetContext.width != width || !widgetContext.height || widgetContext.height != height) {
if (width > 0 && height > 0) {
widgetContext.$container.css('height', height + 'px');
widgetContext.$container.css('width', width + 'px');
widgetContext.width = width;
widgetContext.height = height;
sizeChanged = true;
}
}
return sizeChanged;
}
function onResize() {
if (checkSize()) {
if (widgetContext.inited) {
if (cafs['resize']) {
cafs['resize']();
cafs['resize'] = null;
}
cafs['resize'] = tbRaf(function() {
try {
widgetTypeInstance.onResize();
} catch (e) {
handleWidgetException(e);
}
});
} else if (gridsterItemInited) {
onInit();
}
}
}
function gridsterItemInitialized(item) {
if (item && item.gridster) {
widgetContext.isMobile = item.gridster.isMobile;
gridsterItemInited = true;
if (checkSize()) {
onInit();
}
}
}
function onEditModeChanged(isEdit) {
if (widgetContext.isEdit != isEdit) {
widgetContext.isEdit = isEdit;
if (widgetContext.inited) {
if (cafs['editMode']) {
cafs['editMode']();
cafs['editMode'] = null;
}
cafs['editMode'] = tbRaf(function() {
try {
widgetTypeInstance.onEditModeChanged();
} catch (e) {
handleWidgetException(e);
}
});
}
}
}
function onMobileModeChanged(isMobile) {
if (widgetContext.isMobile != isMobile) {
widgetContext.isMobile = isMobile;
if (widgetContext.inited) {
if (cafs['mobileMode']) {
cafs['mobileMode']();
cafs['mobileMode'] = null;
}
cafs['mobileMode'] = tbRaf(function() {
try {
widgetTypeInstance.onMobileModeChanged();
} catch (e) {
handleWidgetException(e);
}
});
}
}
}
function isNumeric(val) {
return (val - parseFloat( val ) + 1) >= 0;
}
function formatValue(value, dec, units) {
if (angular.isDefined(value) &&
value !== null && isNumeric(value)) {
var formatted = value;
if (angular.isDefined(dec)) {
formatted = formatted.toFixed(dec);
}
formatted = (formatted * 1).toString();
if (angular.isDefined(units) && units.length > 0) {
formatted += ' ' + units;
}
return formatted;
} else {
return '';
}
}
function onDestroy() {
for (var id in widgetContext.subscriptions) {
var subscription = widgetContext.subscriptions[id];
subscription.destroy();
}
widgetContext.subscriptions = [];
if (widgetContext.inited) {
widgetContext.inited = false;
for (var cafId in cafs) {
if (cafs[cafId]) {
cafs[cafId]();
cafs[cafId] = null;
}
}
try {
widgetTypeInstance.onDestroy();
} catch (e) {
handleWidgetException(e);
}
}
}
}