/**
 * 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');
require('utils/configs_collection');
var stringUtils = require('utils/string_utils');
var validator = require('utils/validator');

var configTagFromFileNameMap = {};
var PASSWORD = "PASSWORD";

App.config = Em.Object.create({

  CONFIG_GROUP_NAME_MAX_LENGTH: 18,

  /**
   * filename exceptions used to support substandard sitenames which don't have "xml" extension
   * @type {string[]}
   */
  filenameExceptions: ['alert_notification'],

  preDefinedServiceConfigs: [],

  /**
   * Map for methods used to parse hosts lists from certain config properties
   */
  uniqueHostsListParsers: [
    {
      propertyName: 'templeton.hive.properties',
      type: 'webhcat-site',
      method: 'getTempletonHiveHosts'
    }
  ],

  /**
   *
   * Returns file name version that stored on server.
   *
   * Example:
   *   App.config.getOriginalFileName('core-site') // returns core-site.xml
   *   App.config.getOriginalFileName('zoo.cfg') // returns zoo.cfg
   *
   * @param {String} fileName
   * @method getOriginalFileName
   **/
  getOriginalFileName: function (fileName) {
    if (/\.xml$/.test(fileName)) return fileName;
    return this.get('filenameExceptions').contains(fileName) ? fileName : fileName + '.xml';
  },

  /**
   * truncate Config Group name to <CONFIG_GROUP_NAME_MAX_LENGTH> length and paste "..." in the middle
   */
  truncateGroupName: function (name) {
    if (name && name.length > App.config.CONFIG_GROUP_NAME_MAX_LENGTH) {
      var middle = Math.floor(App.config.CONFIG_GROUP_NAME_MAX_LENGTH / 2);
      name = name.substring(0, middle) + "..." + name.substring(name.length - middle);
    }
    return name;
  },

  /**
   * Check if Hive installation with new MySQL database created via Ambari is allowed
   * @param osFamily
   * @returns {boolean}
   */
  isManagedMySQLForHiveAllowed: function (osFamily) {
    var osList = ['redhat5', 'suse11'];
    return !osList.contains(osFamily);
  },

  /**
   *
   * Returns the configuration tagName from supplied filename
   *
   * Example:
   *   App.config.getConfigTagFromFileName('core-site.xml') // returns core-site
   *   App.config.getConfigTagFromFileName('zoo.cfg') // returns zoo.cfg
   *
   * @param {String} fileName
   * @method getConfigTagFromFileName
   **/
  getConfigTagFromFileName: function (fileName) {
    if (configTagFromFileNameMap[fileName]) {
      return configTagFromFileNameMap[fileName];
    }
    var ret = fileName.endsWith('.xml') ? fileName.slice(0, -4) : fileName;
    configTagFromFileNameMap[fileName] = ret;
    return ret;
  },

  /**
   *
   * @param name
   * @param fileName
   * @returns {string}
   */
  configId: function(name, fileName) {
    return name + "__" + App.config.getConfigTagFromFileName(fileName);
  },

  setPreDefinedServiceConfigs: function (isMiscTabToBeAdded) {
    var stackServices = App.StackService.find().filterProperty('id');
    // Only include services that has configTypes related to them for service configuration page
    var servicesWithConfigTypes = stackServices.filter(function (service) {
      var configtypes = service.get('configTypes');
      return configtypes && !!Object.keys(configtypes).length;
    }, this);

    var allTabs;
    if (isMiscTabToBeAdded) {
      var nonServiceTab = require('data/service_configs');
      var miscService = nonServiceTab.findProperty('serviceName', 'MISC');
      var tagTypes = {};
      servicesWithConfigTypes.mapProperty('configTypes').forEach(function (configTypes) {
        for (var fileName in configTypes) {
          if (fileName.endsWith('-env') && !miscService.get('configTypes')[fileName]) {
            tagTypes[fileName] = configTypes[fileName];
          }
        }
      });
      miscService.set('configTypes', $.extend(miscService.get('configTypes'), tagTypes));
      allTabs = servicesWithConfigTypes.concat(nonServiceTab);
    } else {
      allTabs = servicesWithConfigTypes;
    }
    this.set('preDefinedServiceConfigs', allTabs);
  },

  secureConfigs: require('data/HDP2/secure_mapping'),

  secureConfigsMap: function () {
    var ret = {};
    this.get('secureConfigs').forEach(function (sc) {
      ret[sc.name] = true;
    });
    return ret;
  }.property('secureConfigs.[]'),

  kerberosIdentities: require('data/HDP2/kerberos_identities').configProperties,

  kerberosIdentitiesMap: function() {
    var map = {};

    this.get('kerberosIdentities').forEach(function (c) {
      map[this.configId(c.name, c.filename)] = c;
    }, this);
    return map;
  }.property('kerberosIdentities'),

  customStackMapping: require('data/custom_stack_map'),

  mapCustomStack: function () {
    var
      baseStackFolder = App.get('currentStackName'),
      singMap = {
        "1": [">", ">="],
        "-1": ["<", "<="],
        "0": ["=", ">=","<="]
      };

    this.get('customStackMapping').every(function (stack) {
      if(stack.stackName == App.get('currentStackName')){
        var versionCompare = Em.compare(App.get('currentStackVersionNumber'), stack.stackVersionNumber);
        if(singMap[versionCompare+""].contains(stack.sign)){
          baseStackFolder = stack.baseStackFolder;
          return false;
        }
      }
      return true;
    });

    return baseStackFolder;
  },

  allPreDefinedSiteProperties: function() {
    var sitePropertiesForCurrentStack = this.preDefinedConfigFile(this.mapCustomStack(), 'site_properties');
    if (sitePropertiesForCurrentStack) {
      return sitePropertiesForCurrentStack.configProperties;
    } else if (App.get('isHadoop23Stack')) {
      return require('data/HDP2.3/site_properties').configProperties;
    } else {
      return require('data/HDP2.2/site_properties').configProperties;
    }
  }.property('App.isHadoop23Stack'),

  preDefinedSiteProperties: function () {
    var serviceNames = App.StackService.find().mapProperty('serviceName').concat('MISC');
    return this.get('allPreDefinedSiteProperties').filter(function(p) {
      return serviceNames.contains(p.serviceName);
    });
  }.property('allPreDefinedSiteProperties'),

  /**
   * map of <code>preDefinedSiteProperties</code> provide search by index
   * @type {object}
   */
  preDefinedSitePropertiesMap: function () {
    var map = {};

    this.get('preDefinedSiteProperties').forEach(function (c) {
      map[this.configId(c.name, c.filename)] = c;
    }, this);
    return map;
  }.property('preDefinedSiteProperties'),

  preDefinedConfigFile: function(folder, file) {
    try {
      return require('data/{0}/{1}'.format(folder, file));
    } catch (err) {
      // the file doesn't exist, which might be expected.
    }
  },

  serviceByConfigTypeMap: function () {
    var ret = {};
    App.StackService.find().forEach(function(s) {
      s.get('configTypeList').forEach(function (ct) {
        ret[ct] = s;
      });
    });
    return ret;
  }.property(),

  /**
   * Generate configs collection with Ember or plain config objects
   * from config JSON
   *
   * @param configJSON
   * @param useEmberObject
   * @returns {Array}
   */
  getConfigsFromJSON: function(configJSON, useEmberObject) {
    var configs = [],
      filename = App.config.getOriginalFileName(configJSON.type),
      properties = configJSON.properties,
      attributes = [];
      ['FINAL', 'PASSWORD', 'USER', 'GROUP', 'TEXT', 'ADDITIONAL_USER_PROPERTY', 'NOT_MANAGED_HDFS_PATH', 'VALUE_FROM_PROPERTY_FILE'].forEach(function (attribute){
        var json = {};
        json[attribute] = Em.get(configJSON, 'properties_attributes.' + attribute.toLowerCase()) || {};
        attributes.push(json);
      });

    for (var index in properties) {
      var serviceConfigObj = this.getDefaultConfig(index, filename);

      if (serviceConfigObj.isRequiredByAgent !== false) {
        serviceConfigObj.value = serviceConfigObj.savedValue = this.formatPropertyValue(serviceConfigObj, properties[index]);
        serviceConfigObj.isFinal = serviceConfigObj.savedIsFinal = attributes[0]['FINAL'][index] === "true";

        var propertyType = [];
        // iterate through all the attributes, except for FINAL
        for (var i=1; i<attributes.length; i++) {
          for (var type in attributes[i]) {
            if (attributes[i][type][index] === "true") {
              propertyType.push(type);

              if (type === PASSWORD) {
                serviceConfigObj.displayType = "password";
              }
            }
          }
        }
        serviceConfigObj.propertyType = propertyType;
        serviceConfigObj.isEditable = serviceConfigObj.isReconfigurable;
      }

      if (useEmberObject) {
        configs.push(App.ServiceConfigProperty.create(serviceConfigObj));
      } else {
        configs.push(serviceConfigObj);
      }
    }
    return configs;
  },

  /**
   * Get config from configsCollections or
   * generate new default config in collection does not contain
   * such config
   *
   * @param name
   * @param fileName
   * @param coreObject
   * @returns {*|Object}
   */
  getDefaultConfig: function(name, fileName, coreObject) {
    var cfg = App.configsCollection.getConfigByName(name, fileName) ||
      App.config.createDefaultConfig(name, fileName, false);
    if (Em.typeOf(coreObject) === 'object') {
      Em.setProperties(cfg, coreObject);
    }
    return cfg;
  },

  /**
   * This method sets default values for config property
   * These property values has the lowest priority and can be overridden be stack/UI
   * config property but is used when such properties are absent in stack/UI configs
   * @param {string} name
   * @param {string} fileName
   * @param {boolean} definedInStack
   * @param {Object} [coreObject]
   * @returns {Object}
   */
  createDefaultConfig: function(name, fileName, definedInStack, coreObject) {
    var service = this.get('serviceByConfigTypeMap')[App.config.getConfigTagFromFileName(fileName)];
    var serviceName = service ? service.get('serviceName') : 'MISC';
    var tpl = {
      /** core properties **/
      id: this.configId(name, fileName),
      name: name,
      filename: this.getOriginalFileName(fileName),
      value: '',
      savedValue: null,
      isFinal: false,
      savedIsFinal: null,
      /** UI and Stack properties **/
      recommendedValue: null,
      recommendedIsFinal: null,
      supportsFinal: this.shouldSupportFinal(serviceName, fileName),
      supportsAddingForbidden: this.shouldSupportAddingForbidden(serviceName, fileName),
      serviceName: serviceName,
      displayName: name,
      displayType: (coreObject && coreObject.propertyType && coreObject.propertyType.contains(PASSWORD)) ? 'password' : this.getDefaultDisplayType(coreObject ? coreObject.value : ''),
      description: '',
      category: this.getDefaultCategory(definedInStack, fileName),
      isSecureConfig: this.getIsSecure(name),
      showLabel: true,
      isVisible: true,
      isUserProperty: !definedInStack,
      isRequired: definedInStack,
      group: null,
      isRequiredByAgent:  true,
      isReconfigurable: true,
      unit: null,
      hasInitialValue: false,
      isOverridable: true,
      index: Infinity,
      dependentConfigPattern: null,
      options: null,
      radioName: null,
      widgetType: null,
      errorMessage: '',
      warnMessage: ''
    };
    return Object.keys(coreObject|| {}).length ?
      $.extend(tpl, coreObject) : tpl;
  },

  /**
   * This method creates host name properties
   * @param serviceName
   * @param componentName
   * @param value
   * @param stackComponent
   * @returns Object
   */
  createHostNameProperty: function(serviceName, componentName, value, stackComponent) {
    var hostOrHosts = stackComponent.get('isMultipleAllowed') ? 'hosts' : 'host';
    var name = componentName.toLowerCase() + '_' + hostOrHosts;
    var filename = serviceName.toLowerCase() + "-site.xml";
    return {
      "id": App.config.configId(name, filename),
      "name": name,
      "displayName":  stackComponent.get('displayName') + ' ' + (value.length > 1 ? 'hosts' : 'host'),
      "value": value,
      "recommendedValue": value,
      "description": "The " + hostOrHosts + " that has been assigned to run " + stackComponent.get('displayName'),
      "displayType": "component" + hostOrHosts.capitalize(),
      "isOverridable": false,
      "isRequiredByAgent": false,
      "serviceName": serviceName,
      "filename": filename,
      "category": componentName,
      "index": 0
    }
  },

  /**
   * Get component name from config name string
   *
   * @param configName
   * @returns {string}
   */
  getComponentName: function(configName) {
    var match = configName.match(/^(.*)_host[s]?$/) || [],
      component = match[1];
    return component ? component.toUpperCase() : "";
  },

  /**
   * This method merge properties form <code>stackConfigProperty<code> which are taken from stack
   * with <code>UIConfigProperty<code> which are hardcoded on UI
   * @param coreObject
   * @param stackProperty
   * @param preDefined
   * @param [propertiesToSkip]
   */
  mergeStaticProperties: function(coreObject, stackProperty, preDefined, propertiesToSkip) {
    propertiesToSkip = propertiesToSkip || ['name', 'filename', 'value', 'savedValue', 'isFinal', 'savedIsFinal'];
    for (var k in coreObject) {
      if (coreObject.hasOwnProperty(k)) {
        if (!propertiesToSkip.contains(k)) {
          coreObject[k] = this.getPropertyIfExists(k, coreObject[k], stackProperty, preDefined);
        }
      }
    }
    return coreObject;
  },

  /**
   * This method using for merging some properties from two objects
   * if property exists in <code>firstPriority<code> result will be it's property
   * else if property exists in <code>secondPriority<code> result will be it's property
   * otherwise <code>defaultValue<code> will be returned
   * @param {String} propertyName
   * @param {*} defaultValue=null
   * @param {Em.Object|Object} firstPriority
   * @param {Em.Object|Object} [secondPriority=null]
   * @returns {*}
   */
  getPropertyIfExists: function(propertyName, defaultValue, firstPriority, secondPriority) {
    firstPriority = firstPriority || {};
    secondPriority = secondPriority || {};
    var fp = Em.get(firstPriority, propertyName);
    if (firstPriority && !Em.isNone(fp)) {
      return fp;
    }
    else {
      var sp = Em.get(secondPriority, propertyName);
      if (secondPriority && !Em.isNone(sp)) {
        return sp;
      } else {
        return defaultValue;
      }
    }
  },

  /**
   * Get displayType for properties that has not defined value
   * @param value
   * @returns {string}
   */
  getDefaultDisplayType: function(value) {
    return value && !stringUtils.isSingleLine(value) ? 'multiLine' : 'string';
  },

  /**
   * Get category for properties that has not defined value
   * @param stackConfigProperty
   * @param fileName
   * @returns {string}
   */
  getDefaultCategory: function(stackConfigProperty, fileName) {
    return (stackConfigProperty ? 'Advanced ' : 'Custom ') + this.getConfigTagFromFileName(fileName);
  },

  /**
   * Get isSecureConfig for properties that has not defined value
   * @param propertyName
   * @returns {boolean}
   */
  getIsSecure: function(propertyName) {
    return !!this.get('secureConfigsMap')[propertyName];
  },

  /**
   * Returns description, formatted if needed
   *
   * @param {String} description
   * @param {String} displayType
   * @returns {String}
   */
  getDescription: function(description, displayType) {
    var additionalDescription = Em.I18n.t('services.service.config.password.additionalDescription');
    if ('password' === displayType) {
      if (description && !description.contains(additionalDescription)) {
        return description + '<br />' + additionalDescription;
      } else {
        return additionalDescription;
      }
    }
    return description
  },

  /**
   * parse Kerberos descriptor
   *
   * @param kerberosDescriptor
   * @returns {{}}
   */
  parseDescriptor: function(kerberosDescriptor) {
    var identitiesMap = {};
    Em.get(kerberosDescriptor, 'KerberosDescriptor.kerberos_descriptor.services').forEach(function (service) {
      this.parseIdentities(service, identitiesMap);
      if (Array.isArray(service.components)) {
        service.components.forEach(function (component) {
          this.parseIdentities(component, identitiesMap);
        }, this);
      }
    }, this);
    return identitiesMap;
  },

  /**
   * Looking for configs identities and add them to <code>identitiesMap<code>
   *
   * @param item
   * @param identitiesMap
   */
  parseIdentities: function (item, identitiesMap) {
    if (item.identities) {
      item.identities.forEach(function (identity) {

        Em.keys(identity).without('name').forEach(function (item) {
          if (identity[item].configuration) {
            var cfg = identity[item].configuration.split('/'), name = cfg[1], fileName = cfg[0];
            identitiesMap[App.config.configId(name, fileName)] = true;
          }
        });
      });
    }
    return identitiesMap;
  },

  /**
   * Update description for disabled kerberos configs which are identities
   *
   * @param description
   * @returns {*}
   */
  kerberosIdentitiesDescription: function(description) {
    if (!description) return Em.I18n.t('services.service.config.secure.additionalDescription');
    description = description.trim();
    return (description.endsWith('.') ? description + ' ' : description + '. ') +
      Em.I18n.t('services.service.config.secure.additionalDescription');
  },

  /**
   * Get view class based on display type of config
   *
   * @param displayType
   * @param dependentConfigPattern
   * @param unit
   * @returns {*}
   */
  getViewClass: function (displayType, dependentConfigPattern, unit) {
    switch (displayType) {
      case 'user':
      case 'group':
        return App.ServiceConfigTextFieldUserGroupWithID;
      case 'checkbox':
      case 'boolean':
        return dependentConfigPattern ? App.ServiceConfigCheckboxWithDependencies : App.ServiceConfigCheckbox;
      case 'password':
        return App.ServiceConfigPasswordField;
      case 'combobox':
        return App.ServiceConfigComboBox;
      case 'radio button':
        return App.ServiceConfigRadioButtons;
      case 'directories':
        return App.ServiceConfigTextArea;
      case 'directory':
        return App.ServiceConfigTextField;
      case 'content':
        return App.ServiceConfigTextAreaContent;
      case 'multiLine':
        return App.ServiceConfigTextArea;
      case 'custom':
        return App.ServiceConfigBigTextArea;
      case 'componentHost':
        return App.ServiceConfigMasterHostView;
      case 'label':
        return App.ServiceConfigLabelView;
      case 'componentHosts':
        return App.ServiceConfigComponentHostsView;
      case 'supportTextConnection':
        return App.checkConnectionView;
      case 'capacityScheduler':
        return App.CapacitySceduler;
      default:
        return unit ? App.ServiceConfigTextFieldWithUnit : App.ServiceConfigTextField;
    }
  },

  /**
   * Returns error validator function based on config type
   *
   * @param displayType
   * @returns {Function}
   */
  getErrorValidator: function (displayType) {
    switch (displayType) {
      case 'checkbox':
      case 'custom':
        return function () {
          return ''
        };
      case 'int':
        return function (value) {
          return !validator.isValidInt(value) && !validator.isConfigValueLink(value)
            ? Em.I18n.t('errorMessage.config.number.integer') : '';
        };
      case 'float':
        return function (value) {
          return !validator.isValidFloat(value) && !validator.isConfigValueLink(value)
            ? Em.I18n.t('errorMessage.config.number.float') : '';
        };
      case 'directories':
      case 'directory':
        return function (value, name) {
          if (App.config.isDirHeterogeneous(name)) {
            if (!validator.isValidDataNodeDir(value)) return Em.I18n.t('errorMessage.config.directory.heterogeneous');
          } else {
            if (!validator.isValidDir(value)) return Em.I18n.t('errorMessage.config.directory.default');
          }
          if (!validator.isAllowedDir(value)) {
            return Em.I18n.t('errorMessage.config.directory.allowed');
          }
          return validator.isNotTrimmedRight(value) ? Em.I18n.t('errorMessage.config.spaces.trailing') : '';
        };
      case 'email':
        return function (value) {
          return !validator.isValidEmail(value) ? Em.I18n.t('errorMessage.config.mail') : '';
        };
      case 'supportTextConnection':
      case 'host':
        return function (value) {
          return validator.isNotTrimmed(value) ? Em.I18n.t('errorMessage.config.spaces.trim') : '';
        };
      case 'password':
        return function (value, name, retypedPassword) {
          if (name === 'ranger_admin_password') {
            if (String(value).length < 9) {
              return Em.I18n.t('errorMessage.config.password.length').format(9);
            }
          }
          return value !== retypedPassword ? Em.I18n.t('errorMessage.config.password') : '';
        };
      case 'user':
      case 'database':
      case 'db_user':
        return function (value) {
          return !validator.isValidDbName(value) ? Em.I18n.t('errorMessage.config.user') : '';
        };
      case 'ldap_url':
        return function (value) {
          return !validator.isValidLdapsURL(value) ? Em.I18n.t('errorMessage.config.ldapUrl') : '';
        };
      default:
        return function (value, name) {
          if (['javax.jdo.option.ConnectionURL', 'oozie.service.JPAService.jdbc.url'].contains(name)
            && !validator.isConfigValueLink(value) && validator.isConfigValueLink(value)) {
            return Em.I18n.t('errorMessage.config.spaces.trim');
          }
          return validator.isNotTrimmedRight(value) ? Em.I18n.t('errorMessage.config.spaces.trailing') : '';
        };
    }
  },

  /**
   * Returns warning validator function based on config type
   *
   * @param displayType
   * @returns {Function}
   */
  getWarningValidator: function(displayType) {
    switch (displayType) {
      case 'int':
      case 'float':
        return function (value, name, filename, stackConfigProperty, unitLabel) {
          stackConfigProperty = stackConfigProperty || App.configsCollection.getConfigByName(name, filename);
          var maximum = Em.get(stackConfigProperty || {}, 'valueAttributes.maximum'),
            minimum = Em.get(stackConfigProperty || {}, 'valueAttributes.minimum'),
            min = validator.isValidFloat(minimum) ? parseFloat(minimum) : NaN,
            max = validator.isValidFloat(maximum) ? parseFloat(maximum) : NaN,
            val = validator.isValidFloat(value) ? parseFloat(value) : NaN;

          if (!isNaN(val) && !isNaN(max) && val > max) {
            return Em.I18n.t('config.warnMessage.outOfBoundaries.greater').format(max + unitLabel);
          }
          if (!isNaN(val) && !isNaN(min) && val < min) {
            return Em.I18n.t('config.warnMessage.outOfBoundaries.less').format(min + unitLabel);
          }
          return '';
        };
      default:
        return function () { return ''; }
    }
  },

  /**
   * Defines if config support heterogeneous devices
   *
   * @param {string} name
   * @returns {boolean}
   */
  isDirHeterogeneous: function(name) {
    return ['dfs.datanode.data.dir'].contains(name);
  },

  /**
   * format property value depending on displayType
   * and one exception for 'kdc_type'
   * @param serviceConfigProperty
   * @param [originalValue]
   * @returns {*}
   */
  formatPropertyValue: function(serviceConfigProperty, originalValue) {
    var value = Em.isNone(originalValue) ? Em.get(serviceConfigProperty, 'value') : originalValue,
        displayType = Em.get(serviceConfigProperty, 'displayType') || Em.get(serviceConfigProperty, 'valueAttributes.type');
    if (Em.get(serviceConfigProperty, 'name') === 'kdc_type') {
      return App.router.get('mainAdminKerberosController.kdcTypesValues')[value];
    }
    if ( /^\s+$/.test("" + value)) {
      return " ";
    }
    switch (displayType) {
      case 'int':
        if (/\d+m$/.test(value) ) {
          return value.slice(0, value.length - 1);
        } else {
          var int = parseInt(value);
          return isNaN(int) ? "" : int.toString();
        }
      case 'float':
        var float = parseFloat(value);
        return isNaN(float) ? "" : float.toString();
      case 'componentHosts':
        if (typeof(value) == 'string') {
          return value.replace(/\[|]|'|&apos;/g, "").split(',');
        }
        return value;
      case 'content':
      case 'string':
      case 'multiLine':
      case 'directories':
      case 'directory':
        return this.trimProperty({ displayType: displayType, value: value });
      default:
        return value;
    }

  },

  /**
   * Format float value
   *
   * @param {*} value
   * @returns {string|*}
   */
  formatValue: function(value) {
    return validator.isValidFloat(value) ? parseFloat(value).toString() : value;
  },

  /**
   * Get step config by file name
   *
   * @param stepConfigs
   * @param fileName
   * @returns {Object|null}
   */
  getStepConfigForProperty: function (stepConfigs, fileName) {
    return stepConfigs.find(function (s) {
      return s.get('configTypes').contains(App.config.getConfigTagFromFileName(fileName));
    });
  },

  /**
   *
   * @param configs
   * @returns {Object[]}
   */
  sortConfigs: function(configs) {
    return configs.sort(function(a, b) {
      if (Em.get(a, 'index') > Em.get(b, 'index')) return 1;
      if (Em.get(a, 'index') < Em.get(b, 'index')) return -1;
      if (Em.get(a, 'name') > Em.get(b, 'name')) return 1;
      if (Em.get(a, 'name') < Em.get(b, 'name')) return -1;
      return 0;
    });
  },

  /**
   * create new ServiceConfig object by service name
   * @param {string} serviceName
   * @param {App.ServiceConfigGroup[]} [configGroups]
   * @param {App.ServiceConfigProperty[]} [configs]
   * @param {Number} [initConfigsLength]
   * @return {App.ServiceConfig}
   * @method createServiceConfig
   */
  createServiceConfig: function (serviceName, configGroups, configs, initConfigsLength) {
    var preDefinedServiceConfig = App.config.get('preDefinedServiceConfigs').findProperty('serviceName', serviceName);
    return App.ServiceConfig.create({
      serviceName: preDefinedServiceConfig.get('serviceName'),
      displayName: preDefinedServiceConfig.get('displayName'),
      configCategories: preDefinedServiceConfig.get('configCategories'),
      configs: configs || [],
      configGroups: configGroups || [],
      initConfigsLength: initConfigsLength || 0
    });
  },

  /**
   * GETs all cluster level sites in one call.
   *
   * @return {$.ajax}
   */
  loadConfigsByTags: function (tags) {
    var urlParams = [];
    tags.forEach(function (_tag) {
      urlParams.push('(type=' + _tag.siteName + '&tag=' + _tag.tagName + ')');
    });
    var params = urlParams.join('|');
    return App.ajax.send({
      name: 'config.on_site',
      sender: this,
      data: {
        params: params
      }
    });
  },

  configTypesInfoMap: {},

  /**
   * Get config types and config type attributes from stack service
   *
   * @param service
   * @return {object}
   */
  getConfigTypesInfoFromService: function (service) {
    var configTypesInfoMap = this.get('configTypesInfoMap');
    if (configTypesInfoMap[service]) {
      // don't recalculate
      return configTypesInfoMap[service];
    }
    var configTypes = service.get('configTypes');
    var configTypesInfo = {
      items: [],
      supportsFinal: [],
      supportsAddingForbidden: []
    };
    if (configTypes) {
      for (var key in configTypes) {
        if (configTypes.hasOwnProperty(key)) {
          configTypesInfo.items.push(key);
          if (configTypes[key].supports && configTypes[key].supports.final === "true") {
            configTypesInfo.supportsFinal.push(key);
          }
          if (configTypes[key].supports && configTypes[key].supports.adding_forbidden === "true"){
            configTypesInfo.supportsAddingForbidden.push(key);
          }
        }
      }
    }
    configTypesInfoMap[service] = configTypesInfo;
    this.set('configTypesInfoMap', configTypesInfoMap);
    return configTypesInfo;
  },

  /**
   *
   * @param configs
   */
  addYarnCapacityScheduler: function(configs) {
    var value = '', savedValue = '', recommendedValue = '',
      excludedConfigs = App.config.getPropertiesFromTheme('YARN');

    var connectedConfigs = configs.filter(function(config) {
      return !excludedConfigs.contains(App.config.configId(config.get('name'), config.get('filename'))) && (config.get('filename') === 'capacity-scheduler.xml');
    });
    var names = connectedConfigs.mapProperty('name');

    connectedConfigs.forEach(function (config) {
      value += config.get('name') + '=' + config.get('value') + '\n';
      if (!Em.isNone(config.get('savedValue'))) {
        savedValue += config.get('name') + '=' + config.get('savedValue') + '\n';
      }
      if (!Em.isNone(config.get('recommendedValue'))) {
        recommendedValue += config.get('name') + '=' + config.get('recommendedValue') + '\n';
      }
    }, this);

    var isFinal = connectedConfigs.someProperty('isFinal', true);
    var savedIsFinal = connectedConfigs.someProperty('savedIsFinal', true);
    var recommendedIsFinal = connectedConfigs.someProperty('recommendedIsFinal', true);

    var cs = App.config.createDefaultConfig('capacity-scheduler', 'capacity-scheduler.xml', true, {
      'value': value,
      'serviceName': 'YARN',
      'savedValue': savedValue || null,
      'recommendedValue': recommendedValue || null,
      'isFinal': isFinal,
      'savedIsFinal': savedIsFinal,
      'recommendedIsFinal': recommendedIsFinal,
      'category': 'CapacityScheduler',
      'displayName': 'Capacity Scheduler',
      'description': 'Capacity Scheduler properties',
      'displayType': 'capacityScheduler'
    });

    configs = configs.filter(function(c) {
      return !(names.contains(c.get('name')) && (c.get('filename') === 'capacity-scheduler.xml'));
    });
    configs.push(App.ServiceConfigProperty.create(cs));
    return configs;
  },

  /**
   *
   * @param serviceName
   * @returns {Array}
   */
  getPropertiesFromTheme: function (serviceName) {
    var properties = [];
    App.Tab.find().forEach(function (t) {
      if (!t.get('isAdvanced') && t.get('serviceName') === serviceName) {
        t.get('sections').forEach(function (s) {
          s.get('subSections').forEach(function (ss) {
            properties = properties.concat(ss.get('configProperties'));
          });
        });
      }
    }, this);
    return properties;
  },

  /**
   * transform one config with textarea content
   * into set of configs of file
   * @param configs
   * @param filename
   * @return {*}
   */
  textareaIntoFileConfigs: function (configs, filename) {
    var configsTextarea = configs.findProperty('name', 'capacity-scheduler');
    if (configsTextarea && !App.get('testMode')) {
      var properties = configsTextarea.get('value').split('\n');

      properties.forEach(function (_property) {
        var name, value;
        if (_property) {
          _property = _property.split('=');
          name = _property[0];
          value = (_property[1]) ? _property[1] : "";
          configs.push(Em.Object.create({
            name: name,
            value: value,
            savedValue: value,
            serviceName: configsTextarea.get('serviceName'),
            filename: filename,
            isFinal: configsTextarea.get('isFinal'),
            isNotDefaultValue: configsTextarea.get('isNotDefaultValue'),
            isRequiredByAgent: configsTextarea.get('isRequiredByAgent'),
            group: null
          }));
        }
      });
      return configs.without(configsTextarea);
    }
    return configs;
  },

  /**
   * trim trailing spaces for all properties.
   * trim both trailing and leading spaces for host displayType and hive/oozie datebases url.
   * for directory or directories displayType format string for further using.
   * for password and values with spaces only do nothing.
   * @param {Object} property
   * @returns {*}
   */
  trimProperty: function (property) {
    var displayType = Em.get(property, 'displayType');
    var value = Em.get(property, 'value');
    var name = Em.get(property, 'name');
    var rez;
    switch (displayType) {
      case 'directories':
      case 'directory':
        rez = value.replace(/,/g, ' ').trim().split(/\s+/g).join(',');
        break;
      case 'host':
        rez = value.trim();
        break;
      case 'password':
        break;
      default:
        if (name == 'javax.jdo.option.ConnectionURL' || name == 'oozie.service.JPAService.jdbc.url') {
          rez = value.trim();
        }
        rez = (typeof value == 'string') ? value.replace(/(\s+$)/g, '') : value;
    }
    return ((rez == '') || (rez == undefined)) ? value : rez;
  },

  /**
   * Generate minimal config property object used in *_properties.js files.
   * Example:
   * <code>
   *   var someProperties = App.config.generateConfigPropertiesByName([
   *    'property_1', 'property_2', 'property_3'], { category: 'General', filename: 'myFileName'});
   *   // someProperties contains Object[]
   *   [
   *    {
   *      name: 'property_1',
   *      displayName: 'property_1',
   *      isVisible: true,
   *      isReconfigurable: true,
   *      category: 'General',
   *      filename: 'myFileName'
   *    },
   *    .......
   *   ]
   * </code>
   * @param {string[]} names
   * @param {Object} properties - additional properties which will merge with base object definition
   * @returns {object[]}
   * @method generateConfigPropertiesByName
   */
  generateConfigPropertiesByName: function (names, properties) {
    return names.map(function (item) {
      var baseObj = {
        name: item
      };
      if (properties) return $.extend(baseObj, properties);
      else return baseObj;
    });
  },

  /**
   * load cluster stack configs from server and run mapper
   * @returns {$.ajax}
   * @method loadConfigsFromStack
   */
  loadClusterConfigsFromStack: function () {
    return App.ajax.send({
      name: 'configs.stack_configs.load.cluster_configs',
      sender: this,
      data: {
        stackVersionUrl: App.get('stackVersionURL')
      },
      success: 'saveConfigsToModel'
    });
  },

  /**
   * load stack configs from server and run mapper
   * @param {String[]} [serviceNames=null]
   * @returns {$.ajax}
   * @method loadConfigsFromStack
   */
  loadConfigsFromStack: function (serviceNames) {
    serviceNames = serviceNames || [];
    var name = serviceNames.length > 0 ? 'configs.stack_configs.load.services' : 'configs.stack_configs.load.all';
    return App.ajax.send({
      name: name,
      sender: this,
      data: {
        stackVersionUrl: App.get('stackVersionURL'),
        serviceList: serviceNames.join(',')
      },
      success: 'saveConfigsToModel'
    });
  },

  /**
   * Runs <code>stackConfigPropertiesMapper<code>
   * @param {object} data
   * @method saveConfigsToModel
   */
  saveConfigsToModel: function (data) {
    App.stackConfigPropertiesMapper.map(data);
  },

  /**
   * Check if config filename supports final attribute
   * @param serviceName
   * @param filename
   * @returns {boolean}
   */
  shouldSupportFinal: function (serviceName, filename) {
    var unsupportedServiceNames = ['MISC', 'Cluster'];
    if (!serviceName || unsupportedServiceNames.contains(serviceName) || !filename) {
      return false;
    } else {
      var stackService = App.StackService.find(serviceName);
      if (!stackService) {
        return false;
      }
      return !!this.getConfigTypesInfoFromService(stackService).supportsFinal.find(function (configType) {
        return filename.startsWith(configType);
      });
    }
  },

  shouldSupportAddingForbidden: function(serviceName, filename) {
    var unsupportedServiceNames = ['MISC', 'Cluster'];
    if (!serviceName || unsupportedServiceNames.contains(serviceName) || !filename) {
      return false;
    } else {
      var stackServiceName = App.StackService.find().findProperty('serviceName', serviceName);
      if (!stackServiceName) {
        return false;
      }
      var stackService = App.StackService.find(serviceName);
      return !!this.getConfigTypesInfoFromService(stackService).supportsAddingForbidden.find(function (configType) {
        return filename.startsWith(configType);
      });
    }
  },

  /**
   * Remove all ranger-related configs, that should be available only if Ranger is installed
   * @param configs - stepConfigs object
   */
  removeRangerConfigs: function (configs) {
    configs.forEach(function (service) {
      var filteredConfigs = [];
      service.get('configs').forEach(function (config) {
        if (!/^ranger-/.test(config.get('filename'))) {
          filteredConfigs.push(config);
        }
      });
      service.set('configs', filteredConfigs);
      var filteredCategories = [];
      service.get('configCategories').forEach(function (category) {
        if (!/ranger-/.test(category.get('name'))) {
          filteredCategories.push(category);
        }
      });
      service.set('configCategories', filteredCategories);
    });
  },

  /**
   * Create config with non default config group. Some custom config properties
   * can be created and assigned to non-default config group.
   *
   * @param {Em.Object} override - config value
   * @param {Em.Object} configGroup - config group to set
   * @return {Object}
   **/
  createCustomGroupConfig: function (override, configGroup) {
    App.assertObject(override);
    App.assertEmberObject(configGroup);

    var newOverride = App.ServiceConfigProperty.create(this.createDefaultConfig(override.propertyName, override.filename, false, override));

    newOverride.setProperties({
      'isOriginalSCP': false,
      'overrides': null,
      'group': configGroup,
      'parentSCP': null,
      isCustomGroupConfig: true
    });

    if (!configGroup.get('properties.length')) {
      configGroup.set('properties', Em.A([]));
    }
    configGroup.set('properties', configGroup.get('properties').concat(newOverride));

    return newOverride;
  },


  /**
   * @param {App.ServiceConfigProperty} serviceConfigProperty
   * @param {Object} override - plain object with properties that is different from parent SCP
   * @param {App.ServiceConfigGroup} configGroup
   * @returns {App.ServiceConfigProperty}
   */
  createOverride: function(serviceConfigProperty, override, configGroup) {
    App.assertObject(serviceConfigProperty);
    App.assertEmberObject(configGroup);

    if (Em.isNone(serviceConfigProperty.get('overrides'))) serviceConfigProperty.set('overrides', []);

    var newOverride = App.ServiceConfigProperty.create(serviceConfigProperty);

    newOverride.setProperties({ 'savedValue': null, 'savedIsFinal': null });

    if (!Em.isNone(override)) {
      for (var key in override) {
        newOverride.set(key, override[key]);
      }
    }

    newOverride.setProperties({
      'isOriginalSCP': false,
      'overrides': null,
      'group': configGroup,
      'parentSCP': serviceConfigProperty
    });

    if (!configGroup.get('properties.length')) {
      configGroup.set('properties', Em.A([]));
    }
    configGroup.set('properties', configGroup.get('properties').concat(newOverride));

    serviceConfigProperty.get('overrides').pushObject(newOverride);

    var savedOverrides = serviceConfigProperty.get('overrides').filter(function (override) {
      return !Em.isNone(Em.get(override, 'savedValue'));
    });
    serviceConfigProperty.set('overrideValues', savedOverrides.mapProperty('savedValue'));
    serviceConfigProperty.set('overrideIsFinalValues', savedOverrides.mapProperty('savedIsFinal'));

    return newOverride;
  },


  /**
   * Merge values in "stored" to "base" if name matches, it's a value only merge.
   * @param base {Array} Em.Object
   * @param stored {Array} Object
   * @returns {Object[]|Em.Object[]} base
   */
  mergeStoredValue: function(base, stored) {
    if (stored) {
      base.forEach(function (p) {
        var sp = stored.filterProperty('filename', p.filename).findProperty('name', p.name);
        if (sp) {
          Em.set(p, 'value', Em.get(sp, 'value'));
        }
      });
    }
    return base;
  },


  /**
   * Helper method to get property from the <code>stepConfigs</code>
   *
   * @param {String} name - config property name
   * @param {String} fileName - config property filename
   * @param {Object[]} stepConfigs
   * @return {App.ServiceConfigProperty|Boolean} - App.ServiceConfigProperty instance or <code>false</code> when property not found
   */
  findConfigProperty: function(stepConfigs, name, fileName) {
    if (!name && !fileName) return false;
    if (stepConfigs && stepConfigs.length) {
      return stepConfigs.mapProperty('configs').filter(function(item) {
        return item.length;
      }).reduce(function(p, c) {
        if (p) {
          return p.concat(c);
        }
      }).filterProperty('filename', fileName).findProperty('name', name);
    }
    return false;
  },

  getTempletonHiveHosts: function (value) {
    var pattern = /thrift:\/\/.+:\d+/,
      patternMatch = value.match(pattern);
    return patternMatch ? patternMatch[0].split('\\,') : [];
  },

  /**
   * Update config property value based on its current value and list of zookeeper server hosts.
   * Used to prevent sort order issues.
   * <code>siteConfigs</code> object formatted according server's persist format e.g.
   *
   * <code>
   *   {
   *     'yarn-site': {
   *       'property_name1': 'property_value1'
   *       'property_name2': 'property_value2'
   *       .....
   *     }
   *   }
   * </code>
   *
   * @method updateHostsListValue
   * @param {Object} siteConfigs - prepared site config object to store
   * @param {String} propertyType - type of the property to update
   * @param {String} propertyName - name of the property to update
   * @param {String} hostsList - list of ZooKeeper Server names to set as config property value
   * @param {Boolean} isArray - determines whether value string is formatted as array
   * @return {String} - result value
   */
  updateHostsListValue: function(siteConfigs, propertyType, propertyName, hostsList, isArray) {
    var value = hostsList,
      propertyHosts = (siteConfigs[propertyName] || ''),
      hostsToSet = hostsList,
      parser = this.get('uniqueHostsListParsers').find(function (property) {
        return property.type === propertyType && property.propertyName === propertyName;
      });
    if (parser) {
      propertyHosts = this.get(parser.method)(propertyHosts);
      hostsToSet = this.get(parser.method)(hostsToSet);
    } else {
      if (isArray) {
        var pattern = /(^\[|]$)/g;
        propertyHosts = propertyHosts.replace(pattern, '');
        hostsToSet = hostsToSet.replace(pattern, '');
      }
      propertyHosts = propertyHosts.split(',');
      hostsToSet = hostsToSet.split(',');
    }

    if (!Em.isEmpty(siteConfigs[propertyName])) {
      var diffLength = propertyHosts.filter(function(hostName) {
        return !hostsToSet.contains(hostName);
      }).length;
      if (diffLength == 0 && propertyHosts.length == hostsToSet.length) {
        value = siteConfigs[propertyName];
      }
    }
    siteConfigs[propertyName] = value;
    return value;
  },

  /**
   * Load cluster-env configs mapped to array
   * @return {*|{then}}
   */
  getClusterEnvConfigs: function () {
    var dfd = $.Deferred();
    App.ajax.send({
      name: 'config.cluster_env_site',
      sender: this
    }).done(function (data) {
      App.router.get('configurationController').getConfigsByTags([{
        siteName: data.items[data.items.length - 1].type,
        tagName: data.items[data.items.length - 1].tag
      }]).done(function (clusterEnvConfigs) {
        var configsObject = clusterEnvConfigs[0].properties;
        var configsArray = [];
        for (var property in configsObject) {
          if (configsObject.hasOwnProperty(property)) {
            configsArray.push(Em.Object.create({
              name: property,
              value: configsObject[property],
              filename: 'cluster-env.xml'
            }));
          }
        }
        dfd.resolve(configsArray);
      });
    });
    return dfd.promise();
  }
});
