text: /**
   * 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.
   */
  
  var App = require('app');
  
  var stringUtils = require('utils/string_utils');
  
  App.alertDefinitionsMapper = App.QuickDataMapper.create({
  
    model: App.AlertDefinition,
    reportModel: App.AlertReportDefinition,
    metricsSourceModel: App.AlertMetricsSourceDefinition,
    metricsUriModel: App.AlertMetricsUriDefinition,
  
    config: {
      id: 'AlertDefinition.id',
      name: 'AlertDefinition.name',
      description: 'AlertDefinition.description',
      label: 'AlertDefinition.label',
      service_id: 'AlertDefinition.service_name',
      service_name: 'AlertDefinition.service_name',
      component_name: 'AlertDefinition.component_name',
      enabled: 'AlertDefinition.enabled',
      scope: 'AlertDefinition.scope',
      interval: 'AlertDefinition.interval',
      type: 'AlertDefinition.source.type',
      reporting_key: 'reporting',
      reporting_type: 'array',
      reporting: {
        item: 'id'
      }
    },
  
    portConfig: {
      default_port: 'AlertDefinition.source.default_port',
      port_uri: 'AlertDefinition.source.uri'
    },
  
    aggregateConfig: {
      alert_name: 'AlertDefinition.source.alert_name'
    },
  
    scriptConfig: {
      location: 'AlertDefinition.source.path'
    },
  
    uriConfig: {
      id: 'AlertDefinition.source.uri.id',
      http: 'AlertDefinition.source.uri.http',
      https: 'AlertDefinition.source.uri.https',
      https_property: 'AlertDefinition.source.uri.https_property',
      https_property_value: 'AlertDefinition.source.uri.https_property_value'
    },
  
    map: function (json) {
      if (json && json.items) {
  
        var self = this,
            alertDefinitions = [],
            alertReportDefinitions = [],
            alertMetricsSourceDefinitions = [],
            alertMetricsUriDefinitions = [],
            alertGroupsMap = App.cache['previousAlertGroupsMap'],
            existingAlertDefinitions = App.AlertDefinition.find(),
            alertDefinitionsToDelete = existingAlertDefinitions.mapProperty('id'),
            rawSourceData = {};
  
        json.items.forEach(function (item) {
          var convertedReportDefinitions = [];
          var reporting = item.AlertDefinition.source.reporting;
          for (var report in reporting) {
            if (reporting.hasOwnProperty(report)) {
              if (report == "units") {
                convertedReportDefinitions.push({
                  id: item.AlertDefinition.id + report,
                  type: report,
                  text: reporting[report]
                });
              } else {
                convertedReportDefinitions.push({
                  id: item.AlertDefinition.id + report,
                  type: report,
                  text: reporting[report].text,
                  value: reporting[report].value
                });
              }
            }
          }
  
          alertReportDefinitions = alertReportDefinitions.concat(convertedReportDefinitions);
          item.reporting = convertedReportDefinitions;
  
          rawSourceData[item.AlertDefinition.id] = item.AlertDefinition.source;
          item.AlertDefinition.description = item.AlertDefinition.description || '';
  
          var alertDefinition = this.parseIt(item, this.get('config'));
  
          if (alertGroupsMap[alertDefinition.id]) {
            alertDefinition.groups = alertGroupsMap[alertDefinition.id];
          }
  
          var oldAlertDefinition = existingAlertDefinitions.findProperty('id', alertDefinition.id);
          if (oldAlertDefinition) {
            // new values will be parsed in the another mapper, so for now just use old values
            alertDefinition.summary = oldAlertDefinition.get('summary');
            alertDefinition.last_triggered = oldAlertDefinition.get('lastTriggered');
          }
  
          alertDefinitionsToDelete = alertDefinitionsToDelete.without(alertDefinition.id);
  
          // map properties dependent on Alert Definition type
          switch (item.AlertDefinition.source.type) {
            case 'PORT':
              alertDefinitions.push($.extend(alertDefinition, this.parseIt(item, this.get('portConfig'))));
              break;
            case 'METRIC':
              // map App.AlertMetricsSourceDefinition's
              var jmxMetric = item.AlertDefinition.source.jmx;
              var gangliaMetric = item.AlertDefinition.source.ganglia;
              if (jmxMetric) {
                alertDefinition.jmx_id = item.AlertDefinition.id + 'jmx';
                alertMetricsSourceDefinitions.push({
                  id: alertDefinition.jmx_id,
                  value: jmxMetric.value,
                  property_list: jmxMetric.property_list
                });
              }
              if (gangliaMetric) {
                alertDefinition.ganglia_id = item.AlertDefinition.id + 'ganglia';
                alertMetricsSourceDefinitions.push({
                  id: alertDefinition.ganglia_id,
                  value: gangliaMetric.value,
                  property_list: gangliaMetric.property_list
                });
              }
  
              // map App.AlertMetricsUriDefinition
              alertDefinition.uri_id = item.AlertDefinition.id + 'uri';
              item.AlertDefinition.source.uri.id = alertDefinition.uri_id;
              alertMetricsUriDefinitions.push(this.parseIt(item, this.get('uriConfig')));
              alertDefinitions.push(alertDefinition);
              break;
            case 'WEB':
              // map App.AlertMetricsUriDefinition
              alertDefinition.uri_id = item.AlertDefinition.id + 'uri';
              item.AlertDefinition.source.uri.id = alertDefinition.uri_id;
              alertMetricsUriDefinitions.push(this.parseIt(item, this.get('uriConfig')));
              alertDefinitions.push(alertDefinition);
              break;
            case 'AGGREGATE':
              alertDefinitions.push($.extend(alertDefinition, this.parseIt(item, this.get('aggregateConfig'))));
              break;
            case 'SCRIPT':
              alertDefinitions.push($.extend(alertDefinition, this.parseIt(item, this.get('scriptConfig'))));
              break;
            default:
              console.error('Incorrect Alert Definition type:', item.AlertDefinition);
          }
        }, this);
  
        alertDefinitionsToDelete.forEach(function(definitionId) {
          self.deleteRecord(existingAlertDefinitions.findProperty('id', definitionId));
        });
  
        // load all mapped data to model
        App.store.loadMany(this.get('reportModel'), alertReportDefinitions);
        App.store.loadMany(this.get('metricsSourceModel'), alertMetricsSourceDefinitions);
        this.setMetricsSourcePropertyLists(this.get('metricsSourceModel'), alertMetricsSourceDefinitions);
        App.store.loadMany(this.get('metricsUriModel'), alertMetricsUriDefinitions);
        App.store.loadMany(this.get('model'), alertDefinitions);
        this.setAlertDefinitionsRawSourceData(rawSourceData);
        if (App.router.get('mainAlertDefinitionsController')) {
          App.router.set('mainAlertDefinitionsController.mapperTimestamp', (new Date()).getTime());
        }
        App.store.commit();
      }
    },
  
    /**
     * set propertyList properties from <code>data</code> for records in <code>model</code>
     * @param model
     * @param data
     */
    setMetricsSourcePropertyLists: function (model, data) {
      data.forEach(function (record) {
        model.find().findProperty('id', record.id).set('propertyList', record.property_list);
      });
    },
  
    /**
     * set rawSourceDate properties for <code>App.AlertDefinition</code> records
     * @param rawSourceData
     */
    setAlertDefinitionsRawSourceData: function (rawSourceData) {
      var allDefinitions = App.AlertDefinition.find();
      for (var alertDefinitionId in rawSourceData) {
        if (rawSourceData.hasOwnProperty(alertDefinitionId)) {
          allDefinitions.findProperty('id', +alertDefinitionId).set('rawSourceData', rawSourceData[alertDefinitionId]);
        }
      }
    }
  });
  