text: /*
   * Copyright © 2016-2019 The Thingsboard Authors
   *
   * Licensed 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.
   */
  export default angular.module('thingsboard.api.alarm', [])
      .factory('alarmService', AlarmService)
      .name;
  
  /*@ngInject*/
  function AlarmService($http, $q, $interval, $filter, $timeout, utils, types) {
  
      var alarmSourceListeners = {};
  
      var simulatedAlarm = {
          createdTime: (new Date).getTime(),
          startTs: (new Date).getTime(),
          endTs: 0,
          ackTs: 0,
          clearTs: 0,
          originatorName: 'Simulated',
          originator: {
              entityType: "DEVICE",
              id: "1"
          },
          type: 'TEMPERATURE',
          severity: "MAJOR",
          status: types.alarmStatus.activeUnack,
          details: {
              message: "Temperature is high!"
          }
      };
  
      var service = {
          getAlarm: getAlarm,
          getAlarmInfo: getAlarmInfo,
          saveAlarm: saveAlarm,
          ackAlarm: ackAlarm,
          clearAlarm: clearAlarm,
          getAlarms: getAlarms,
          getHighestAlarmSeverity: getHighestAlarmSeverity,
          pollAlarms: pollAlarms,
          cancelPollAlarms: cancelPollAlarms,
          subscribeForAlarms: subscribeForAlarms,
          unsubscribeFromAlarms: unsubscribeFromAlarms
      }
  
      return service;
  
      function getAlarm(alarmId, ignoreErrors, config) {
          var deferred = $q.defer();
          var url = '/api/alarm/' + alarmId;
          if (!config) {
              config = {};
          }
          config = Object.assign(config, { ignoreErrors: ignoreErrors });
          $http.get(url, config).then(function success(response) {
              deferred.resolve(response.data);
          }, function fail() {
              deferred.reject();
          });
          return deferred.promise;
      }
  
      function getAlarmInfo(alarmId, ignoreErrors, config) {
          var deferred = $q.defer();
          var url = '/api/alarm/info/' + alarmId;
          if (!config) {
              config = {};
          }
          config = Object.assign(config, { ignoreErrors: ignoreErrors });
          $http.get(url, config).then(function success(response) {
              deferred.resolve(response.data);
          }, function fail() {
              deferred.reject();
          });
          return deferred.promise;
      }
  
      function saveAlarm(alarm, ignoreErrors, config) {
          var deferred = $q.defer();
          var url = '/api/alarm';
          if (!config) {
              config = {};
          }
          config = Object.assign(config, { ignoreErrors: ignoreErrors });
          $http.post(url, alarm, config).then(function success(response) {
              deferred.resolve(response.data);
          }, function fail() {
              deferred.reject();
          });
          return deferred.promise;
      }
  
      function ackAlarm(alarmId, ignoreErrors, config) {
          var deferred = $q.defer();
          var url = '/api/alarm/' + alarmId + '/ack';
          if (!config) {
              config = {};
          }
          config = Object.assign(config, { ignoreErrors: ignoreErrors });
          $http.post(url, null, config).then(function success(response) {
              deferred.resolve(response.data);
          }, function fail() {
              deferred.reject();
          });
          return deferred.promise;
      }
  
      function clearAlarm(alarmId, ignoreErrors, config) {
          var deferred = $q.defer();
          var url = '/api/alarm/' + alarmId + '/clear';
          if (!config) {
              config = {};
          }
          config = Object.assign(config, { ignoreErrors: ignoreErrors });
          $http.post(url, null, config).then(function success(response) {
              deferred.resolve(response.data);
          }, function fail() {
              deferred.reject();
          });
          return deferred.promise;
      }
  
      function getAlarms(entityType, entityId, pageLink, alarmSearchStatus, alarmStatus, fetchOriginator, ascOrder, config) {
          var deferred = $q.defer();
          var url = '/api/alarm/' + entityType + '/' + entityId + '?limit=' + pageLink.limit;
  
          if (angular.isDefined(pageLink.startTime) && pageLink.startTime != null) {
              url += '&startTime=' + pageLink.startTime;
          }
          if (angular.isDefined(pageLink.endTime) && pageLink.endTime != null) {
              url += '&endTime=' + pageLink.endTime;
          }
          if (angular.isDefined(pageLink.idOffset) && pageLink.idOffset != null) {
              url += '&offset=' + pageLink.idOffset;
          }
          if (alarmSearchStatus) {
              url += '&searchStatus=' + alarmSearchStatus;
          }
          if (alarmStatus) {
              url += '&status=' + alarmStatus;
          }
          if (fetchOriginator) {
              url += '&fetchOriginator=' + ((fetchOriginator===true) ? 'true' : 'false');
          }
          if (angular.isDefined(ascOrder) && ascOrder != null) {
              url += '&ascOrder=' + (ascOrder ? 'true' : 'false');
          }
  
          $http.get(url, config).then(function success(response) {
              deferred.resolve(response.data);
          }, function fail() {
              deferred.reject();
          });
          return deferred.promise;
      }
  
      function getHighestAlarmSeverity(entityType, entityId, alarmSearchStatus, alarmStatus, config) {
          var deferred = $q.defer();
          var url = '/api/alarm/highestSeverity/' + entityType + '/' + entityId;
  
          if (alarmSearchStatus) {
              url += '?searchStatus=' + alarmSearchStatus;
          } else if (alarmStatus) {
              url += '?status=' + alarmStatus;
          }
          $http.get(url, config).then(function success(response) {
              deferred.resolve(response.data);
          }, function fail() {
              deferred.reject();
          });
          return deferred.promise;
      }
  
      function fetchAlarms(alarmsQuery, pageLink, deferred, alarmsList) {
          getAlarms(alarmsQuery.entityType, alarmsQuery.entityId,
              pageLink, alarmsQuery.alarmSearchStatus, alarmsQuery.alarmStatus,
              alarmsQuery.fetchOriginator, false, {ignoreLoading: true}).then(
              function success(alarms) {
                  if (!alarmsList) {
                      alarmsList = [];
                  }
                  alarmsList = alarmsList.concat(alarms.data);
                  if (alarms.hasNext && !alarmsQuery.limit) {
                      fetchAlarms(alarmsQuery, alarms.nextPageLink, deferred, alarmsList);
                  } else {
                      alarmsList = $filter('orderBy')(alarmsList, ['-createdTime']);
                      deferred.resolve(alarmsList);
                  }
              },
              function fail() {
                  deferred.reject();
              }
          );
      }
  
      function getAlarmsByQuery(alarmsQuery) {
          var deferred = $q.defer();
          var time = Date.now();
          var pageLink;
          if (alarmsQuery.limit) {
              pageLink = {
                  limit: alarmsQuery.limit
              };
          } else if (alarmsQuery.interval) {
              pageLink = {
                  limit: 100,
                  startTime: time - alarmsQuery.interval
              };
          } else if (alarmsQuery.startTime) {
              pageLink = {
                  limit: 100,
                  startTime: Math.round(alarmsQuery.startTime)
              }
              if (alarmsQuery.endTime) {
                  pageLink.endTime = Math.round(alarmsQuery.endTime);
              }
          }
  
          fetchAlarms(alarmsQuery, pageLink, deferred);
          return deferred.promise;
      }
  
      function onPollAlarms(alarmsQuery) {
          getAlarmsByQuery(alarmsQuery).then(
              function success(alarms) {
                  alarmsQuery.onAlarms(alarms);
              },
              function fail() {}
          );
      }
  
      function pollAlarms(entityType, entityId, alarmStatus, interval, limit, pollingInterval, onAlarms) {
          var alarmsQuery = {
              entityType: entityType,
              entityId: entityId,
              alarmSearchStatus: null,
              alarmStatus: alarmStatus,
              fetchOriginator: false,
              interval: interval,
              limit: limit,
              onAlarms: onAlarms
          };
          onPollAlarms(alarmsQuery);
          return $interval(onPollAlarms, pollingInterval, 0, false, alarmsQuery);
      }
  
      function cancelPollAlarms(pollPromise) {
          if (angular.isDefined(pollPromise)) {
              $interval.cancel(pollPromise);
          }
      }
  
      function subscribeForAlarms(alarmSourceListener) {
          alarmSourceListener.id = utils.guid();
          alarmSourceListeners[alarmSourceListener.id] = alarmSourceListener;
          var alarmSource = alarmSourceListener.alarmSource;
          if (alarmSource.type == types.datasourceType.function) {
              $timeout(function() {
                  alarmSourceListener.alarmsUpdated([simulatedAlarm], false);
              });
          } else if (alarmSource.entityType && alarmSource.entityId) {
              var pollingInterval = alarmSourceListener.alarmsPollingInterval;
              alarmSourceListener.alarmsQuery = {
                  entityType: alarmSource.entityType,
                  entityId: alarmSource.entityId,
                  alarmSearchStatus: alarmSourceListener.alarmSearchStatus,
                  alarmStatus: null
              }
              var originatorKeys = $filter('filter')(alarmSource.dataKeys, {name: 'originator'});
              if (originatorKeys && originatorKeys.length) {
                  alarmSourceListener.alarmsQuery.fetchOriginator = true;
              }
              var subscriptionTimewindow = alarmSourceListener.subscriptionTimewindow;
              if (subscriptionTimewindow.realtimeWindowMs) {
                  alarmSourceListener.alarmsQuery.startTime = subscriptionTimewindow.startTs;
              } else {
                  alarmSourceListener.alarmsQuery.startTime = subscriptionTimewindow.fixedWindow.startTimeMs;
                  alarmSourceListener.alarmsQuery.endTime = subscriptionTimewindow.fixedWindow.endTimeMs;
              }
              alarmSourceListener.alarmsQuery.onAlarms = function(alarms) {
                  if (subscriptionTimewindow.realtimeWindowMs) {
                      var now = Date.now();
                      if (alarmSourceListener.lastUpdateTs) {
                          var interval = now - alarmSourceListener.lastUpdateTs;
                          alarmSourceListener.alarmsQuery.startTime += interval;
                      }
                      alarmSourceListener.lastUpdateTs = now;
                  }
                  alarmSourceListener.alarmsUpdated(alarms, false);
              }
              onPollAlarms(alarmSourceListener.alarmsQuery);
              alarmSourceListener.pollPromise = $interval(onPollAlarms, pollingInterval,
                  0, false, alarmSourceListener.alarmsQuery);
          }
  
      }
  
      function unsubscribeFromAlarms(alarmSourceListener) {
          if (alarmSourceListener && alarmSourceListener.id) {
              if (alarmSourceListener.pollPromise) {
                  $interval.cancel(alarmSourceListener.pollPromise);
                  alarmSourceListener.pollPromise = null;
              }
              delete alarmSourceListeners[alarmSourceListener.id];
          }
      }
  }
  