/**
 * 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');
var fileUtils = require('utils/file_utils');
require('./wizardStep_controller');

App.WizardStep8Controller = App.WizardStepController.extend(App.AddSecurityConfigs, App.wizardDeployProgressControllerMixin, App.ConfigOverridable, App.ConfigsSaverMixin, {

  name: 'wizardStep8Controller',

  stepName: 'step8',

  /**
   * @type {boolean}
   */
  isAddService: Em.computed.equal('content.controllerName', 'addServiceController'),

  /**
   * @type {boolean}
   */
  isAddHost: Em.computed.equal('content.controllerName', 'addHostController'),

  /**
   * @type {boolean}
   */
  isInstaller: Em.computed.equal('content.controllerName', 'installerController'),

  /**
   * List of raw data about cluster that should be displayed
   * @type {Array}
   */
  rawContent: [
    {
      config_name: 'Admin',
      display_name: 'Admin Name',
      config_value: ''
    },
    {
      config_name: 'cluster',
      display_name: 'Cluster Name',
      config_value: ''
    },
    {
      config_name: 'hosts',
      display_name: 'Total Hosts',
      config_value: ''
    },
    {
      config_name: 'Repo',
      display_name: 'Local Repository',
      config_value: ''
    }
  ],

  /**
   * List of data about cluster (based on formatted <code>rawContent</code>)
   * @type {Object[]}
   */
  clusterInfo: [],

  /**
   * List of services with components assigned to hosts
   * @type {Object[]}
   */
  services: [],

  /**
   * @type {Object[]}
   */
  configs: [],

  /**
   * True if Kerberos is installed on the cluster and the kdc_type on the server is set to "none"
   * @type {Boolean}
   */
  isManualKerberos: Em.computed.equal('App.router.mainAdminKerberosController.kdc_type', 'none'),

  showDownloadCsv: function () {
    return !!App.get('router.mainAdminKerberosController.kdc_type')
  }.property('App.router.mainAdminKerberosController.kdc_type'),


  /**
   * Should Submit button be disabled
   * @type {bool}
   */
  isSubmitDisabled: false,

  /**
   * Should Back button be disabled
   * @type {bool}
   */
  isBackBtnDisabled: false,

  /**
   * Is error appears while <code>ajaxQueue</code> executes
   * @type {bool}
   */
  hasErrorOccurred: false,

  /**
   * Are services installed
   * Used to hide Deploy Progress Bar
   * @type {bool}
   */
  servicesInstalled: false,

  /**
   * List of service config tags
   * @type {Object[]}
   */
  serviceConfigTags: [],

  /**
   * Selected config group
   * @type {Object}
   */
  selectedConfigGroup: null,

  /**
   * List of config groups
   * @type {Object[]}
   */
  configGroups: [],

  selectedServices: function () {
    const services = App.StackService.find().map(service => service);
    return services;
  }.property(),

  selectedMpacks: function() {
    return this.get('content.selectedMpacks') || this.get('wizardController').getDBProperty('selectedMpacks');
  }.property(),

  downloadConfig: function() {
    return this.get('content.downloadConfig') || this.get('wizardController').getDBProperty('downloadConfig');
  }.property(),

  getSelectedStack: function() {
    const selectedStack = this.get('content.selectedStack');
    const stack = this.get('wizardController').getStack(selectedStack.name, selectedStack.version);
    return stack;    
  },

  installedServices: function() {
    const services = App.StackService.find().filter(service => service.get('isInstalled') === true);
    return services;
  }.property(),

  /**
   * Current cluster name
   * @type {string}
   */
  clusterName: Em.computed.alias('content.cluster.name'),

  /**
   * List of existing cluster names
   * @type {string[]}
   */
  clusterNames: [],

  /**
   * Number of completed cluster delete requests
   * @type {number}
   */
  clusterDeleteRequestsCompleted: 0,

  /**
   * Number of existing repo_versions
   * @type {number}
   */
  existingRepositoryVersions: 0,

  /**
   * Indicates if all cluster delete requests are completed
   * @type {boolean}
   */
  isAllClusterDeleteRequestsCompleted: Em.computed.equalProperties('clusterDeleteRequestsCompleted', 'clusterNames.length'),

  /**
   * Error popup body views for clusters that couldn't be deleted
   * @type {App.AjaxDefaultErrorPopupBodyView[]}
   */
  clusterDeleteErrorViews: [],

  /**
   * Clear current step data
   * @method clearStep
   */
  clearStep: function () {
    this.get('services').clear();
    this.get('configs').clear();
    this.get('clusterInfo').clear();
    this.get('serviceConfigTags').clear();
    this.set('servicesInstalled', false);
    this.set('ajaxQueueLength', 0);
    this.set('ajaxRequestsQueue', App.ajaxQueue.create());
    this.set('ajaxRequestsQueue.finishedCallback', this.ajaxQueueFinished);
    this.get('clusterDeleteErrorViews').clear();
    this.set('clusterDeleteRequestsCompleted', 0);
  },

  /**
   * Load current step data
   * @method loadStep
   */
  loadStep: function () {
    this.clearStep();
    if (this.get('content.serviceConfigProperties')) {
      this.formatProperties();
      this.loadConfigs();
    }
    this.loadClusterInfo();
    this.loadServices();
    this.set('isSubmitDisabled', false);
    this.set('isBackBtnDisabled', false);
  },

  /**
   * replace whitespace character with coma between directories
   * @method formatProperties
   */
  formatProperties: function () {
    this.get('content.serviceConfigProperties').forEach(function (_configProperty) {
      _configProperty.value = typeof _configProperty.value === "boolean"
        ? _configProperty.value.toString() : App.config.trimProperty(_configProperty, false);
    });
  },

  /**
   * Load all site properties
   * @method loadConfigs
   */
  loadConfigs: function () {
    this.set('configs', this.get('content.serviceConfigProperties').filter(function (config) {
      return !config.group;
    }));
  },

  /**
   * Format <code>content.hosts</code> from Object to Array
   * @returns {Array}
   * @method getRegisteredHosts
   */
  getRegisteredHosts: function () {
    var allHosts = this.get('content.hosts');
    var hosts = [];
    for (var hostName in allHosts) {
      if (allHosts.hasOwnProperty(hostName)) {
        if (allHosts[hostName].bootStatus === 'REGISTERED') {
          allHosts[hostName].hostName = allHosts[hostName].name;
          hosts.pushObject(allHosts[hostName]);
        }
      }
    }
    return hosts;
  },

  /**
   * Load all info about cluster to <code>clusterInfo</code> variable
   * @method loadClusterInfo
   */
  loadClusterInfo: function () {

    //Admin name
    var admin = this.rawContent.findProperty('config_name', 'Admin');
    admin.config_value = App.db.getLoginName();
    if (admin.config_value) {
      this.get('clusterInfo').pushObject(Ember.Object.create(admin));
    }

    // cluster name
    var cluster = this.rawContent.findProperty('config_name', 'cluster');
    cluster.config_value = this.get('content.cluster.name');
    this.get('clusterInfo').pushObject(Ember.Object.create(cluster));

    //hosts
    var newHostsCount = 0;
    var totalHostsCount = 0;
    var hosts = this.get('content.hosts');
    for (var hostName in hosts) {
      newHostsCount += ~~!hosts[hostName].isInstalled;
      totalHostsCount++;
    }

    var totalHostsObj = this.rawContent.findProperty('config_name', 'hosts');
    totalHostsObj.config_value = totalHostsCount + ' (' + newHostsCount + ' new)';
    this.get('clusterInfo').pushObject(Em.Object.create(totalHostsObj));

    //repo
    if (this.get('isAddService') || this.get('isAddHost')) {
      // For some stacks there is no info regarding stack versions to upgrade, e.g. HDP-2.1
      if (App.StackVersion.find().get('content.length')) {
        this.loadRepoInfo();
      } else {
        this.loadDefaultRepoInfo();
      }
    } else {
      // from install wizard
      var downloadConfig = this.get('downloadConfig');
      var selectedStack = this.getSelectedStack();
      var allRepos = [];
      if (selectedStack && selectedStack.get('operatingSystems')) {
        selectedStack.get('operatingSystems').forEach(function (os) {
          if (os.get('isSelected')) {
            os.get('repositories').forEach(function(repo) {
              if (repo.get('showRepo')) {
                allRepos.push(Em.Object.create({
                  base_url: repo.get('baseUrl'),
                  os_type: repo.get('osType'),
                  repo_id: repo.get('repoId')
                }));
              }
            }, this);
          }
        }, this);
      }
      allRepos.set('display_name', Em.I18n.t("installer.step8.repoInfo.displayName"));
      this.get('clusterInfo').set('useRedhatSatellite', downloadConfig.useRedhatSatellite);
      this.get('clusterInfo').set('repoInfo', allRepos);
    }
  },

  /**
   * Load repo info for add Service/Host wizard review page
   * @return {$.ajax|null}
   * @method loadRepoInfo
   */
  loadRepoInfo: function () {
    var stackName = App.get('currentStackName');
    var currentStackVersionNumber = App.get('currentStackVersionNumber');
    var currentStackVersion = App.StackVersion.find().filterProperty('stack', stackName).findProperty('version', currentStackVersionNumber);
    var currentRepoVersion = currentStackVersion.get('repositoryVersion.repositoryVersion');

    return App.ajax.send({
      name: 'cluster.load_repo_version',
      sender: this,
      data: {
        stackName: stackName,
        repositoryVersion: currentRepoVersion
      },
      success: 'loadRepoInfoSuccessCallback',
      error: 'loadRepoInfoErrorCallback'
    });
  },

  /**
   * Save all repo base URL of all OS type to <code>repoInfo<code>
   * @param {object} data
   * @method loadRepoInfoSuccessCallback
   */
  loadRepoInfoSuccessCallback: function (data) {
    Em.assert('Current repo-version may be only one', data.items.length === 1);
    if (data.items.length) {
      var allRepos = this.generateRepoInfo(Em.getWithDefault(data, 'items.0.repository_versions.0.operating_systems', []));
      allRepos.set('display_name', Em.I18n.t("installer.step8.repoInfo.displayName"));
      this.get('clusterInfo').set('repoInfo', allRepos);
      //if the property is missing, set as false
      this.get('clusterInfo').set('useRedhatSatellite', data.items[0].repository_versions[0].operating_systems[0].OperatingSystems.ambari_managed_repositories === false);
    } else {
      this.loadDefaultRepoInfo();
    }
  },

  /**
   * Generate list regarding info about OS versions and repositories.
   *
   * @param {Object{}} oses - OS array
   * @returns {Em.Object[]}
   */
  generateRepoInfo: function(oses) {
    return oses.map(function(os) {
      return os.repositories.map(function (repository) {
        return Em.Object.create({
          base_url: repository.Repositories.base_url,
          os_type: repository.Repositories.os_type,
          repo_id: repository.Repositories.repo_id
        });
      });
    }).reduce(function(p, c) { return p.concat(c); });
  },

  /**
   * Load repo info from stack. Used if installed stack doesn't have upgrade info.
   *
   * @returns {$.Deferred}
   * @method loadDefaultRepoInfo
   */
  loadDefaultRepoInfo: function() {
    var nameVersionCombo = App.get('currentStackVersion').split('-');

    return App.ajax.send({
      name: 'cluster.load_repositories',
      sender: this,
      data: {
        stackName: nameVersionCombo[0],
        stackVersion: nameVersionCombo[1]
      },
      success: 'loadDefaultRepoInfoSuccessCallback',
      error: 'loadRepoInfoErrorCallback'
    });
  },

  /**
   * @param {Object} data - JSON data from server
   * @method loadDefaultRepoInfoSuccessCallback
   */
  loadDefaultRepoInfoSuccessCallback: function (data) {
    var allRepos = this.generateRepoInfo(Em.getWithDefault(data, 'items', []));
    allRepos.set('display_name', Em.I18n.t("installer.step8.repoInfo.displayName"));
    this.get('clusterInfo').set('repoInfo', allRepos);
    //if the property is missing, set as false
    this.get('clusterInfo').set('useRedhatSatellite', data.items[0].OperatingSystems.ambari_managed_repositories === false);
  },

  /**
   * @method loadRepoInfoErrorCallback
   */
  loadRepoInfoErrorCallback: function () {
    var allRepos = [];
    allRepos.set('display_name', Em.I18n.t("installer.step8.repoInfo.displayName"));
    this.get('clusterInfo').set('repoInfo', allRepos);
  },

  /**
   * Load all info about services to <code>services</code> variable
   * @method loadServices
   */
  loadServices: function () {
    this.get('selectedServices').filterProperty('isHiddenOnSelectServicePage', false).forEach(function (service) {
      var serviceObj = Em.Object.create({
        service_name: service.get('serviceName'),
        display_name: service.get('displayNameOnSelectServicePage'),
        service_components: Em.A([])
      });
      service.get('serviceComponents').forEach(function (component) {
        // show clients for services that have only clients components
        if ((component.get('isClient') || component.get('isRequiredOnAllHosts')) && !service.get('isClientOnlyService')) return;
        // no HA component
        if (component.get('isHAComponentOnly')) return;
        // skip if component is not allowed on single node cluster
        if (Object.keys(this.get('content.hosts')).length === 1 && component.get('isNotAllowedOnSingleNodeCluster')) return;
        var displayName;
        if (component.get('isClient')) {
          displayName = Em.I18n.t('common.clients')
        } else {
          // remove service name from component display name
          displayName = App.format.role(component.get('componentName'), false).replace(new RegExp('^' + service.get('serviceName') + '\\s', 'i'), '');
        }

        var componentName = component.get('componentName');
        var masterComponents = this.get('content.masterComponentHosts');
        var isMasterComponentSelected = masterComponents.someProperty('component', componentName);
        var isMaster = component.get('isMaster');

        if (!isMaster || isMasterComponentSelected) {
          serviceObj.get('service_components').pushObject(Em.Object.create({
            component_name: component.get('isClient') ? Em.I18n.t('common.client').toUpperCase() : component.get('componentName'),
            display_name: displayName,
            component_value: this.assignComponentHosts(component)
          }));
        }
      }, this);
      if (service.get('customReviewHandler')) {
        for (var displayName in service.get('customReviewHandler')) {
          serviceObj.get('service_components').pushObject(Em.Object.create({
            display_name: displayName,
            component_value: this.assignComponentHosts(Em.Object.create({
              customHandler: service.get('customReviewHandler.' + displayName)
            }))
          }));
        }
      }
      this.get('services').pushObject(serviceObj);
    }, this);
  },

  /**
   * Set <code>component_value</code> property to <code>component</code>
   * @param {Em.Object} component
   * @return {String}
   * @method assignComponentHosts
   */
  assignComponentHosts: function (component) {
    var componentValue;
    if (component.get('customHandler')) {
      componentValue = this[component.get('customHandler')].call(this, component);
    }
    else {
      if (component.get('isMaster')) {
        componentValue = this.getMasterComponentValue(component.get('componentName'));
      }
      else {
        var componentName = component.get('isClient') ? Em.I18n.t('common.client').toUpperCase() : component.get('componentName');
        var hostsLength = this.get('content.slaveComponentHosts')
          .findProperty('componentName', componentName).hosts.length;
        componentValue = hostsLength + Em.I18n.t('installer.step8.host' + (hostsLength > 1 ? 's' : ''));
      }
    }
    return componentValue;
  },

  getMasterComponentValue: function (componentName) {
    var masterComponents = this.get('content.masterComponentHosts');
    var hostsCount = masterComponents.filterProperty('component', componentName).length;
    return stringUtils.pluralize(hostsCount,
      masterComponents.findProperty('component', componentName).hostName,
        hostsCount + ' ' + Em.I18n.t('installer.step8.hosts'));
  },

  loadHiveDbValue: function() {
    return this.loadDbValue('HIVE');
  },

  loadOozieDbValue: function() {
    return this.loadDbValue('OOZIE');
  },

  /**
   * Set displayed Hive DB value based on DB type
   * @method loadHiveDbValue
   */
  loadDbValue: function (serviceName) {
    var serviceConfigProperties = this.get('content.serviceConfigProperties');
    var dbFull = serviceConfigProperties.findProperty('name', serviceName.toLowerCase() + '_database');
      //db = serviceConfigProperties.findProperty('name', serviceName.toLowerCase() + '_ambari_database');
    //since db.value contains the intial default value of <service>_admin_database (MySQL) and not the actual db type selected,
    //ignore the value when displaying the database name on the summary page
    return dbFull ? dbFull.value : '';
  },

  /**
   * Set displayed HBase master value
   * @param {Object} hbaseMaster
   * @method loadHbaseMasterValue
   */
  loadHbaseMasterValue: function (hbaseMaster) {
    var hbaseHostName = this.get('content.masterComponentHosts').filterProperty('component', hbaseMaster.component_name);
    if (hbaseHostName.length === 1) {
      hbaseMaster.set('component_value', hbaseHostName[0].hostName);
    } else {
      hbaseMaster.set('component_value', hbaseHostName[0].hostName + " " + Em.I18n.t('installer.step8.other').format(hbaseHostName.length - 1));
    }
  },

  /**
   * Set displayed ZooKeeper Server value
   * @param {Object} serverComponent
   * @method loadZkServerValue
   */
  loadZkServerValue: function (serverComponent) {
    var zkHostNames = this.get('content.masterComponentHosts').filterProperty('component', serverComponent.component_name).length;
    var hostSuffix;
    if (zkHostNames === 1) {
      hostSuffix = Em.I18n.t('installer.step8.host');
    } else {
      hostSuffix = Em.I18n.t('installer.step8.hosts');
    }
    serverComponent.set('component_value', zkHostNames + hostSuffix);
  },

  /**
   * Onclick handler for <code>next</code> button
   * @method submit
   * @return {void}
   */
  submit: function () {
    var wizardController;
    if (!this.get('isSubmitDisabled')) {
      wizardController = App.router.get(this.get('content.controllerName'));
      wizardController.setLowerStepsDisable(wizardController.get('currentStep'));
      this.set('isSubmitDisabled', true);
      this.set('isBackBtnDisabled', true);
      this.showRestartWarnings()
        .then(this.checkKDCSession.bind(this));
    }
  },

  /**
   * Warn user about services that will be restarted during installation.
   *
   * @returns {$.Deferred}
   */
  showRestartWarnings: function() {
    var self = this;
    var dfd = $.Deferred();
    var wizardController = App.router.get(this.get('content.controllerName'));
    var selectedServiceNames = this.get('selectedServices').mapProperty('serviceName');
    var installedServiceNames = this.get('installedServices').mapProperty('serviceName');

    if (this.get('isAddService') && selectedServiceNames.contains('OOZIE')) {
      var affectedServices = ['HDFS', 'YARN'].filter(function(serviceName) {
        return installedServiceNames.contains(serviceName);
      });
      if (affectedServices.length) {
        var serviceNames = affectedServices.length > 1 ?
            '<b>{0}</b> {1} <b>{2}</b>'.format(affectedServices[0], Em.I18n.t('and'), affectedServices[1]) : '<b>' + affectedServices[0] + '</b> ';
        App.ModalPopup.show({
          encodeBody: false,
          header: Em.I18n.t('common.warning'),
          body: Em.I18n.t('installer.step8.services.restart.required').format(serviceNames, stringUtils.pluralize(affectedServices.length, Em.I18n.t('common.service').toLowerCase())),
          secondary: Em.I18n.t('common.cancel'),
          primary: Em.I18n.t('common.proceedAnyway'),
          onPrimary: function() {
            this.hide();
            dfd.resolve();
          },
          onClose: function() {
            this.hide();
            self.set('isSubmitDisabled', false);
            self.set('isBackBtnDisabled', false);
            wizardController.setStepsEnable();
            dfd.reject();
          },
          onSecondary: function() {
            this.onClose();
          }
        });
      } else {
        dfd.resolve();
      }
    } else {
      dfd.resolve();
    }
    return dfd.promise();
  },

  checkKDCSession: function() {
    var self = this;
    var wizardController = App.router.get(this.get('content.controllerName'));
    if (!this.get('isInstaller')) {
      App.get('router.mainAdminKerberosController').getKDCSessionState(this.submitProceed.bind(this), function () {
        self.set('isSubmitDisabled', false);
        self.set('isBackBtnDisabled', false);
        wizardController.setStepsEnable();
        if (self.get('isAddService')) {
          wizardController.setSkipSlavesStep(wizardController.getDBProperty('selectedServiceNames'), 3);
        }
      });
    } else {
      this.submitProceed();
    }
  },

  /**
   * Prepare <code>ajaxQueue</code> and start to execute it
   * @method submitProceed
   */
  submitProceed: function () {
    var self = this;
    this.set('clusterDeleteRequestsCompleted', 0);
    this.get('clusterDeleteErrorViews').clear();
    if (this.get('isAddHost')) {
      App.router.get('addHostController').setLowerStepsDisable(4);
    }

    // checkpoint the cluster status on the server so that the user can resume from where they left off
    switch (this.get('content.controllerName')) {
      case 'installerController':
        App.clusterStatus.setClusterStatus({
          clusterName: this.get('clusterName'),
          clusterState: 'CLUSTER_DEPLOY_PREP_2',
          wizardControllerName: this.get('content.controllerName'),
          localdb: App.db.data
        });
        break;
      case 'addHostController':
        App.clusterStatus.setClusterStatus({
          clusterName: this.get('clusterName'),
          clusterState: 'ADD_HOSTS_DEPLOY_PREP_2',
          wizardControllerName: this.get('content.controllerName'),
          localdb: App.db.data
        });
        break;
      case 'addServiceController':
        App.clusterStatus.setClusterStatus({
          clusterName: this.get('clusterName'),
          clusterState: 'ADD_SERVICES_DEPLOY_PREP_2',
          wizardControllerName: this.get('content.controllerName'),
          localdb: App.db.data
        });
        break;
      default:
        break;
    }
    // delete any existing clusters to start from a clean slate
    // before creating a new cluster in install wizard
    // TODO: modify for multi-cluster support
    // this.getExistingClusterNames().complete(function () {
    //   var clusterNames = self.get('clusterNames');
    //   if (self.get('isInstaller') && !App.get('testMode') && clusterNames.length) {
    //     self.deleteClusters(clusterNames);
    //   } else {
    //     self.getExistingVersions();
    //   }
    // });

    this.startDeploy();
  },

  /**
   * Get list of existing cluster names
   * @returns {object|null}
   * returns an array of existing cluster names.
   * returns an empty array if there are no existing clusters.
   * @method getExistingClusterNames
   */
  getExistingClusterNames: function () {
    return App.ajax.send({
      name: 'wizard.step8.existing_cluster_names',
      sender: this,
      success: 'getExistingClusterNamesSuccessCallBack',
      error: 'getExistingClusterNamesErrorCallback'
    });
  },

  /**
   * Save received list to <code>clusterNames</code>
   * @param {Object} data
   * @method getExistingClusterNamesSuccessCallBack
   */
  getExistingClusterNamesSuccessCallBack: function (data) {
    var clusterNames = data.items.mapProperty('Clusters.cluster_name');
    this.set('clusterNames', clusterNames);
  },

  /**
   * If error appears, set <code>clusterNames</code> to <code>[]</code>
   * @method getExistingClusterNamesErrorCallback
   */
  getExistingClusterNamesErrorCallback: function () {
    this.set('clusterNames', []);
  },

  /**
   * Delete cluster by name
   * One request for one cluster!
   * @param {string[]} clusterNames
   * @method deleteClusters
   */
  deleteClusters: function (clusterNames) {
    this.get('clusterDeleteErrorViews').clear();
    clusterNames.forEach(function (clusterName, index) {
      App.ajax.send({
        name: 'common.delete.cluster',
        sender: this,
        data: {
          name: clusterName,
          isLast: index === clusterNames.length - 1
        },
        success: 'deleteClusterSuccessCallback',
        error: 'deleteClusterErrorCallback'
      });
    }, this);

  },

  /**
   * Method to execute after successful cluster deletion
   * @method deleteClusterSuccessCallback
   */
  deleteClusterSuccessCallback: function () {
    this.incrementProperty('clusterDeleteRequestsCompleted');
    if (this.get('isAllClusterDeleteRequestsCompleted')) {
      if (this.get('clusterDeleteErrorViews.length')) {
        this.showDeleteClustersErrorPopup();
      } else {
        this.getExistingVersions();
      }
    }
  },

  /**
   * Method to execute after failed cluster deletion
   * @param {object} request
   * @param {string} ajaxOptions
   * @param {string} error
   * @param {object} opt
   * @method deleteClusterErrorCallback
   */
  deleteClusterErrorCallback: function (request, ajaxOptions, error, opt) {
    this.incrementProperty('clusterDeleteRequestsCompleted');
    try {
      var json = $.parseJSON(request.responseText);
      var message = json.message;
    } catch (err) {
    }
    this.get('clusterDeleteErrorViews').pushObject(App.AjaxDefaultErrorPopupBodyView.create({
      url: opt.url,
      type: opt.type,
      status: request.status,
      message: message
    }));
    if (this.get('isAllClusterDeleteRequestsCompleted')) {
      this.showDeleteClustersErrorPopup();
    }
  },

  /**
   * Show error popup if cluster deletion failed
   * @method showDeleteClustersErrorPopup
   */
  showDeleteClustersErrorPopup: function () {
    var self = this;
    this.setProperties({
      isSubmitDisabled: false,
      isBackBtnDisabled: false
    });
    App.ModalPopup.show({
      header: Em.I18n.t('common.error'),
      secondary: false,
      onPrimary: function () {
        this.hide();
      },
      bodyClass: Em.ContainerView.extend({
        childViews: self.get('clusterDeleteErrorViews')
      })
    });
  },

  /**
   * Get existing repo_versions
   * @method getExistingVersions
   */
  getExistingVersions: function () {
    return App.ajax.send({
      name: 'wizard.get_version_definitions',
      sender: this,
      success: 'getExistingVersionsSuccessCallback'
    });
  },

  /**
   * @param {Object} data
   * @method getExistingVersionsSuccessCallback
   */
  getExistingVersionsSuccessCallback: function (data) {
    if (this.get('isInstaller') && !App.get('testMode') && data.items.length) {
      this.set('existingRepositoryVersions', data.items.length);
      this.deleteExistingVersions(data.items);
    } else {
      this.startDeploy();
    }
  },

  /**
   * Delete existing repo_versions
   * @param {Array} versions
   * @method deleteExistingVersions
   */
  deleteExistingVersions: function (versions) {
    versions.forEach(function (version) {
      App.ajax.send({
        name: 'wizard.delete_repository_versions',
        sender: this,
        data: {
          id: version.VersionDefinition.id,
          stackName: version.VersionDefinition.stack_name,
          stackVersion: version.VersionDefinition.stack_version
        },
        success: 'deleteExistingVersionsSuccessCallback'
      });
    }, this);
  },

  /**
   * Method to execute after successful version deletion
   * @method deleteExistingVersionsSuccessCallback
   */
  deleteExistingVersionsSuccessCallback: function () {
    this.decrementProperty('existingRepositoryVersions');
    if (this.get('existingRepositoryVersions') === 0) {
      this.startDeploy();
    }
  },

  /**
   * updates kerberosDescriptorConfigs
   * @method updateKerberosDescriptor
   */
  updateKerberosDescriptor: function(instant) {
    var kerberosDescriptor = this.get('wizardController').getDBProperty('kerberosDescriptorConfigs');
    var descriptorExists = this.get('wizardController').getDBProperty('isClusterDescriptorExists') === true;

    var ajaxOpts = {
      name: descriptorExists ? 'admin.kerberos.cluster.artifact.update' : 'admin.kerberos.cluster.artifact.create',
      data: {
        artifactName: 'kerberos_descriptor',
        data: {
          artifact_data: kerberosDescriptor
        }
      }
    };
    if (instant) {
      ajaxOpts.sender = this;
      App.ajax.send(ajaxOpts);
    } else {
      this.addRequestToAjaxQueue(ajaxOpts);
    }
  },

  /**
   * Start deploy process
   * @method startDeploy
   */
  startDeploy: function () {
    this.createCluster();
    this.createServiceGroups();
    this.createSelectedServices();
    if (!this.get('isAddHost')) {
      if (this.get('isAddService')) {
        // for manually enabled Kerberos descriptor was updated on transition to this step
        if (App.get('isKerberosEnabled') && !this.get('isManualKerberos')) {
          this.updateKerberosDescriptor();
        }
        var fileNamesToUpdate = this.get('wizardController').getDBProperty('fileNamesToUpdate').uniq();
        if (fileNamesToUpdate && fileNamesToUpdate.length) {
          this.applyConfigurationsToCluster(this.generateDesiredConfigsJSON(this.get('configs'), fileNamesToUpdate));
        }
      }
      this.configureCluster();
      this.createServiceConfigurations();
      this.applyConfigurationsToCluster(this.get('serviceConfigTags'));
    }
    this.createComponents();
    this.registerHostsToCluster();
    this.createConfigurationGroups();
    this.createMasterHostComponents();
    this.createSlaveAndClientsHostComponents();
    if (this.get('isAddService')) {
      this.createAdditionalClientComponents();
    }
    this.createAdditionalHostComponents();

    this.set('ajaxQueueLength', this.get('ajaxRequestsQueue.queue.length'));
    this.get('ajaxRequestsQueue').start();
    this.showLoadingIndicator();
  },

  /**
   * *******************************************************************
   * The following create* functions are called upon submitting Step 8.
   * *******************************************************************
   */

  /**
   * Create cluster using selected stack version
   * Queued request
   * @method createCluster
   */
  createCluster: function () {
    if (!this.get('isInstaller')) return;
    const selectedStack = this.getSelectedStack()
    this.addRequestToAjaxQueue({
      name: 'wizard.step8.create_cluster',
      data: {
        data: JSON.stringify({ "Clusters": {"version": selectedStack.get('stackNameVersion')}})
      },
      success: 'createClusterSuccess'
    });
  },

  createClusterSuccess: function (data, xhr, params) {
    App.set('clusterName', params.cluster);
  },

  /**
   * Creates one service group per mpack.
   * Skip if no mpacks were selected.
   * Queued request
   * @method createServiceGroup
   */
  createServiceGroups: function () {
    if (!this.get('isInstaller')) return;
    
    var data = this.createServiceGroupsData();
    if (data) {
      this.addRequestToAjaxQueue({
        name: 'wizard.step8.create_service_group',
        data: {
          data: JSON.stringify(data)
        }
      });
    } 
  },

  /**
   * Format data for <code>createServiceGroups</code> request
   * @returns {Object[]}
   * @method createServiceGroupsData
   */
  createServiceGroupsData: function () {
    const mpacks = this.get('selectedMpacks');
    
    if (mpacks) {
      const serviceGroups = mpacks.map(mpack => ({
          "ServiceGroupInfo": {
            "service_group_name": `${mpack.name}-${mpack.version}`,
          }
        })
      );

      return serviceGroups;
    }

    return null;
  },

  /**
   * Create selected to install services
   * Queued request
   * Skipped if no services where selected!
   * @method createSelectedServices
   */
  createSelectedServices: function () {
    var data = this.createSelectedServicesData();
    if (!data.length) return;
    this.addRequestToAjaxQueue({
      name: 'wizard.step8.create_selected_services',
      data: {
        data: JSON.stringify(data)
      }
    });
  },

  /**
   * Format data for <code>createSelectedServices</code> request
   * @returns {Object[]}
   * @method createSelectedServicesData
   */
  createSelectedServicesData: function () {
    const services = this.get('selectedServices');
    const data = services.map(service => ({
        "ServiceInfo": {
          "service_name": service.get('serviceName'),
          "service_type": service.get('serviceName'),
          //TODO: mpacks - needs to be revisited when we are no longer hard coding service groups to be named 
          //               for mpacks and when the concept of a "selected stack" is no longer a thing
          "service_group_name": `${service.get('stackName')}-${service.get('stackVersion')}`,
          "desired_stack": `${service.get('stackName')}-${service.get('stackVersion')}`,
        }
      })
    );
    return data;
  },

  /**
   * Create components for selected services
   * Queued requests
   * One request for each service!
   * @method createComponents
   */
  createComponents: function () {
    var serviceComponents = App.StackServiceComponent.find();
    this.get('selectedServices').forEach(function (_service) {
      var serviceName = _service.get('serviceName');
      var componentsData = serviceComponents.filterProperty('serviceName', serviceName).map(function (_component) {
        return { "ServiceComponentInfo": { "component_name": _component.get('componentName') } };
      });

      // Service must be specified in terms of a query for creating multiple components at the same time.
      // See AMBARI-1018.
      this.addRequestToCreateComponent(componentsData, serviceName);
    }, this);

    if (this.get('isAddHost')) {
      var allServiceComponents = [];
      var services = App.Service.find().mapProperty('serviceName');
      services.forEach(function(_service){
        var _serviceComponents = App.Service.find(_service).get('serviceComponents');
        allServiceComponents = allServiceComponents.concat(_serviceComponents);
      }, this);
      this.get('content.slaveComponentHosts').forEach(function (component) {
        if (component.componentName !== 'CLIENT' && !allServiceComponents.contains(component.componentName)) {
          this.addRequestToCreateComponent(
              [{"ServiceComponentInfo": {"component_name": component.componentName}}],
              App.StackServiceComponent.find().findProperty('componentName', component.componentName).get('serviceName')
          );
        }
      }, this);
      this.get('content.clients').forEach(function (component) {
        if (!allServiceComponents.contains(component.component_name)) {
          this.addRequestToCreateComponent(
              [{"ServiceComponentInfo": {"component_name": component.component_name}}],
              App.StackServiceComponent.find().findProperty('componentName', component.component_name).get('serviceName')
          );
        }
      }, this);
    }
  },

  /**
   * Add request to ajax queue to create service component
   * @param componentsData
   * @param serviceName
   */
  addRequestToCreateComponent: function (componentsData, serviceName) {
    this.addRequestToAjaxQueue({
      name: 'wizard.step8.create_components',
      data: {
        data: JSON.stringify(componentsData),
        serviceName: serviceName
      }
    });
  },

  /**
   * Error callback for new service component request
   * So, if component doesn't exist we should create it
   * @param {object} request
   * @param {object} ajaxOptions
   * @param {string} error
   * @param {object} opt
   * @param {object} params
   * @method newServiceComponentErrorCallback
   */
  newServiceComponentErrorCallback: function (request, ajaxOptions, error, opt, params) {
    this.addRequestToAjaxQueue({
      name: 'wizard.step8.create_components',
      data: {
        serviceName: params.serviceName,
        data: JSON.stringify({
          "components": [
            {
              "ServiceComponentInfo": {
                "component_name": params.componentName
              }
            }
          ]
        })
      }
    });
  },

  /**
   * Register hosts
   * Queued request
   * @method registerHostsToCluster
   */
  registerHostsToCluster: function () {
    var data = this.createRegisterHostData();
    if (!data.length) return;
    this.addRequestToAjaxQueue({
      name: 'wizard.step8.register_host_to_cluster',
      data: {
        data: JSON.stringify(data)
      }
    });
  },

  /**
   * Format request-data for <code>registerHostsToCluster</code>
   * @returns {Object}
   * @method createRegisterHostData
   */
  createRegisterHostData: function () {
    return this.getRegisteredHosts().filterProperty('isInstalled', false).map(function (host) {
      return {"Hosts": { "host_name": host.hostName}};
    });
  },

  /**
   * Register new master components
   * @uses registerHostsToComponent
   * @method createMasterHostComponents
   */
  createMasterHostComponents: function () {
    var masterOnAllHosts = [];

    this.get('content.services').filterProperty('isSelected').forEach(function (service) {
      service.get('serviceComponents').filterProperty('isRequiredOnAllHosts').forEach(function (component) {
        if (component.get('isMaster')) {
          masterOnAllHosts.push(component.get('componentName'));
        }
      }, this);
    }, this);

    // create master components for only selected services.
    var selectedMasterComponents = this.get('content.masterComponentHosts').filter(function (_component) {
      return this.get('selectedServices').mapProperty('serviceName').contains(_component.serviceId)
    }, this);
    selectedMasterComponents.mapProperty('component').uniq().forEach(function (component) {
      var hostNames = [];
      if (masterOnAllHosts.length > 0) {
        var compOnAllHosts = false;
        for (var i=0; i < masterOnAllHosts.length; i++) {
          if (component === masterOnAllHosts[i]) {
            compOnAllHosts = true;
            break;
          }
        }
        if (!compOnAllHosts) {
          hostNames = selectedMasterComponents.filterProperty('component', component).filterProperty('isInstalled', false).mapProperty('hostName');
          this.registerHostsToComponent(hostNames, component);
        }
      } else {
        hostNames = selectedMasterComponents.filterProperty('component', component).filterProperty('isInstalled', false).mapProperty('hostName');
        this.registerHostsToComponent(hostNames, component);
      }
    }, this);
  },

  getClientsMap: function (flag) {
    var clients = App.StackServiceComponent.find().filterProperty('isClient'),
      clientsMap = {},
      dependedComponents = flag ? App.StackServiceComponent.find().filterProperty(flag) : App.StackServiceComponent.find();
    clients.forEach(function (client) {
      var clientName = client.get('componentName');
      clientsMap[clientName] = Em.A([]);
      dependedComponents.forEach(function (component) {
        if (component.dependsOn(client))
          clientsMap[clientName].push(component.get('componentName'));
      });
      if (!clientsMap[clientName].length) delete clientsMap[clientName];
    });
    return clientsMap;
  },

  /**
   * Register slave components and clients
   * @uses registerHostsToComponent
   * @method createSlaveAndClientsHostComponents
   */
  createSlaveAndClientsHostComponents: function () {
    var masterHosts = this.get('content.masterComponentHosts');
    var slaveHosts = this.get('content.slaveComponentHosts');
    var clients = this.get('content.clients').filterProperty('isInstalled', false);
    var slaveOnAllHosts = [];
    var clientOnAllHosts = [];

    this.get('content.services').filterProperty('isSelected').forEach(function (service) {
      service.get('serviceComponents').filterProperty('isRequiredOnAllHosts').forEach(function (component) {
        if (component.get('isClient')) {
          clientOnAllHosts.push(component.get('componentName'));
        } else if (component.get('isSlave')) {
          slaveOnAllHosts.push(component.get('componentName'));
        }
      }, this);
    }, this);

    /**
     * Determines on which hosts client should be installed (based on availability of master components on hosts)
     * @type {Object}
     * Format:
     * <code>
     *  {
     *    CLIENT1: Em.A([MASTER1, MASTER2, ...]),
     *    CLIENT2: Em.A([MASTER3, MASTER1, ...])
     *    ...
     *  }
     * </code>
     */
    var clientsToMasterMap = this.getClientsMap('isMaster'),
        clientsToSlaveMap = this.getClientsMap('isSlave');

    slaveHosts.forEach(function (_slave) {
      var hostNames = [];
      var compOnAllHosts;
      if (_slave.componentName !== 'CLIENT') {
        if (slaveOnAllHosts.length > 0) {
          compOnAllHosts = false;
          for (var i=0; i < slaveOnAllHosts.length; i++) {
            if (_slave.componentName === slaveOnAllHosts[i]) {
              // component with ALL cardinality should not
              // registerHostsToComponent in createSlaveAndClientsHostComponents
              compOnAllHosts = true;
              break;
            }
          }
          if (!compOnAllHosts) {
            hostNames = _slave.hosts.filterProperty('isInstalled', false).mapProperty('hostName');
            this.registerHostsToComponent(hostNames, _slave.componentName);
          }
        } else {
          hostNames = _slave.hosts.filterProperty('isInstalled', false).mapProperty('hostName');
          this.registerHostsToComponent(hostNames, _slave.componentName);
        }
      }
      else {
        clients.forEach(function (_client) {
          hostNames = _slave.hosts.mapProperty('hostName');
          // The below logic to install clients to existing/New master hosts should not be applied to Add Host wizard.
          // This is with the presumption that Add Host controller does not add any new Master component to the cluster
          if (!this.get('isAddHost')) {
            if (clientsToMasterMap[_client.component_name]) {
              clientsToMasterMap[_client.component_name].forEach(function (componentName) {
                masterHosts.filterProperty('component', componentName).forEach(function (_masterHost) {
                  hostNames.pushObject(_masterHost.hostName);
                });
              });
            }
          }
          if (clientsToSlaveMap[_client.component_name]) {
            clientsToSlaveMap[_client.component_name].forEach(function (componentName) {
              slaveHosts.filterProperty('componentName', componentName).forEach(function (slaveHost) {
                hostNames = hostNames.concat(slaveHost.hosts.mapProperty('hostName')).uniq();
              });
            });
          }
          if (clientOnAllHosts.length > 0) {
            compOnAllHosts = false;
            for (var i=0; i < clientOnAllHosts.length; i++) {
              if (_client.component_name === clientOnAllHosts[i]) {
                // component with ALL cardinality should not
                // registerHostsToComponent in createSlaveAndClientsHostComponents
                compOnAllHosts = true;
                break;
              }
            }
            if (!compOnAllHosts) {
              hostNames = hostNames.uniq();
              this.registerHostsToComponent(hostNames, _client.component_name);
            }
          } else {
            hostNames = hostNames.uniq();
            this.registerHostsToComponent(hostNames, _client.component_name);
          }
        }, this);
      }
    }, this);
  },

  /**
   * This function is specific to addServiceController
   * Newly introduced master components requires some existing client components to be hosted along with them
   */
  createAdditionalClientComponents: function () {
    var masterHosts = this.get('content.masterComponentHosts');
    var clientHosts = [];
    if (this.get('content.slaveComponentHosts').someProperty('componentName', 'CLIENT')) {
      clientHosts = this.get('content.slaveComponentHosts').findProperty('componentName', 'CLIENT').hosts;
    }
    var clients = this.get('content.clients').filterProperty('isInstalled', false);
    var clientsToMasterMap = this.getClientsMap('isMaster');
    var clientsToClientMap = this.getClientsMap('isClient');
    var installedClients = [];

    // Get all the installed Client components
    this.get('content.services').filterProperty('isInstalled').forEach(function (_service) {
      var serviceClients = App.StackServiceComponent.find().filterProperty('serviceName', _service.get('serviceName')).filterProperty('isClient');
      serviceClients.forEach(function (client) {
        installedClients.push(client.get('componentName'));
      }, this);
    }, this);

    // Check if there is a dependency for being co-hosted between existing client and selected new master
    installedClients.forEach(function (_clientName) {
      if (clientsToMasterMap[_clientName] || clientsToClientMap[_clientName]) {
        var hostNames = [];
        if (clientsToMasterMap[_clientName]) {
          clientsToMasterMap[_clientName].forEach(function (componentName) {
            masterHosts.filterProperty('component', componentName).filterProperty('isInstalled', false).forEach(function (_masterHost) {
              hostNames.pushObject(_masterHost.hostName);
            }, this);
          }, this);
        }
        if (clientsToClientMap[_clientName]) {
          clientsToClientMap[_clientName].forEach(function (componentName) {
            clientHosts.forEach(function (_clientHost) {
              var host = this.get('content.hosts')[_clientHost.hostName];
              var isClientSelected = clients.someProperty('component_name', componentName);
              if (host.isInstalled && isClientSelected && !host.hostComponents.someProperty('HostRoles.component_name', componentName)) {
                hostNames.pushObject(_clientHost.hostName);
              }
            }, this);
          }, this);
        }
        hostNames = hostNames.uniq();
        if (hostNames.length > 0) {
          // If a dependency for being co-hosted is derived between existing client and selected new master but that
          // dependency is already satisfied in the cluster then disregard the derived dependency
          this.removeClientsFromList(_clientName, hostNames);
          this.registerHostsToComponent(hostNames, _clientName);
          if(hostNames.length > 0) {
            this.get('content.additionalClients').pushObject({hostNames: hostNames, componentName: _clientName});
          }
        }
      }
    }, this);
  },

  /**
   *
   * @param clientName
   * @param hostList
   */
  removeClientsFromList: function (clientName, hostList) {
    var clientHosts = [];
    var installedHosts = this.get('content.hosts');
    for (var hostName in installedHosts) {
      if (installedHosts[hostName].isInstalled) {
        if (installedHosts[hostName].hostComponents.mapProperty('HostRoles.component_name').contains(clientName)) {
          clientHosts.push(hostName);
        }
      }
    }

    if (clientHosts.length > 0) {
      clientHosts.forEach(function (hostName) {
        if (hostList.contains(hostName)) {
          hostList.splice(hostList.indexOf(hostName), 1);
        }
      }, this);
    }
  },

  /**
   * Register additional components
   * Based on availability of some services
   * @uses registerHostsToComponent
   * @method createAdditionalHostComponents
   */
  createAdditionalHostComponents: function () {
    var masterHosts = this.get('content.masterComponentHosts');

    // add all components with cardinality == ALL of selected services
    var registeredHosts = this.getRegisteredHosts();
    var notInstalledHosts = registeredHosts.filterProperty('isInstalled', false);
    this.get('content.services').filterProperty('isSelected').forEach(function (service) {
      service.get('serviceComponents').filterProperty('isRequiredOnAllHosts').forEach(function (component) {
        if (service.get('isInstalled') && notInstalledHosts.length) {
          this.registerHostsToComponent(notInstalledHosts.mapProperty('hostName'), component.get('componentName'));
        } else if (!service.get('isInstalled') && registeredHosts.length) {
          this.registerHostsToComponent(registeredHosts.mapProperty('hostName'), component.get('componentName'));
        }
      }, this);
    }, this);

    // add MySQL Server if Hive is selected
    var hiveService = this.get('content.services').filterProperty('isSelected', true).filterProperty('isInstalled', false).findProperty('serviceName', 'HIVE');
    if (hiveService) {
      var hiveDb = this.get('content.serviceConfigProperties').findProperty('name', 'hive_database');
      if (hiveDb.value === "New MySQL Database") {
        this.registerHostsToComponent(masterHosts.filterProperty('component', 'HIVE_SERVER').mapProperty('hostName'), 'MYSQL_SERVER');
      } else if (hiveDb.value === "New PostgreSQL Database") {
        this.registerHostsToComponent(masterHosts.filterProperty('component', 'HIVE_SERVER').mapProperty('hostName'), 'POSTGRESQL_SERVER');
      }
    }
  },

  /**
   * Register component to hosts
   * Queued request
   * @param {String[]} hostNames
   * @param {String} componentName
   * @method registerHostsToComponent
   */
  registerHostsToComponent: function (hostNames, componentName) {
    if (!hostNames.length) return;

    let serviceName,
        serviceGroupName;
    var queryStr = '';
    hostNames.forEach(function (hostName) {
      queryStr += 'Hosts/host_name=' + hostName + '|';
    });
    //slice off last symbol '|'
    queryStr = queryStr.slice(0, -1);

    this.get('selectedServices').forEach( function (service) {
      if (service.get('serviceComponents').findProperty('componentName', componentName)) {
        serviceName = service.get('serviceName');
        serviceGroupName = service.get('stackName') + "-" + service.get('stackVersion');
      }
    });

    var data = {
      "RequestInfo": {
        "query": queryStr
      },
      "Body": {
        "host_components": [
          {
            "HostRoles": {
              "component_name": componentName,
              "service_name": serviceName,
              "service_group_name": serviceGroupName
            }
          }
        ]
      }
    };

    this.addRequestToAjaxQueue({
      name: 'wizard.step8.register_host_to_component',
      data: {
        data: JSON.stringify(data)
      }
    });
  },

  /**
   * Configure cluster settings
   */
  configureCluster: function () {
    const clusterSettings = this.get('configs').filterProperty('filename', 'cluster-settings.xml');
    const data = [];
    clusterSettings.forEach(setting => {
      data.push({
        "ClusterSettingInfo": {
          "cluster_setting_name": setting.name,
          "cluster_setting_value": setting.value
        }
      })
    });

    this.addRequestToAjaxQueue({
      name: 'common.cluster.settings',
      data: {
        clusterName: this.get('clusterName'),
        data: data
      }
    });
  },

  /**
   * Create config objects for services
   * @method createServiceConfigurations
   */
  createServiceConfigurations: function () {
    this.get('selectedServices').forEach(function (service) {
      Object.keys(service.get('configTypes')).forEach(function (type) {
        if (!this.get('serviceConfigTags').someProperty('type', type)) {
          var configs = this.get('configs').filterProperty('filename', App.config.getOriginalFileName(type));
          var serviceConfigNote = this.getServiceConfigNote(type, service.get('displayName'));
          this.get('serviceConfigTags').pushObject(this.createDesiredConfig(type, configs, serviceConfigNote));
        }
      }, this);
    }, this);
    this.createNotification();
  },

  /**
   * Get config version message
   *
   * @param type
   * @param serviceDisplayName
   * @returns {*}
   */
  getServiceConfigNote: function(type, serviceDisplayName) {
    return this.get('isAddService') && type === 'core-site' ?
      Em.I18n.t('dashboard.configHistory.table.notes.addService') : Em.I18n.t('dashboard.configHistory.table.notes.default').format(serviceDisplayName);
  },

  /**
   * Send <code>serviceConfigTags</code> to server
   * Queued request
   * One request for each service config tag
   * @param serviceConfigTags
   * @method applyConfigurationsToCluster
   */
  applyConfigurationsToCluster: function (serviceConfigTags) {
    var allServices = this.get('installedServices').concat(this.get('selectedServices'));
    
    allServices.forEach(function (service) {
      var serviceConfigData = [];
     
      Object.keys(service.get('configTypesRendered')).forEach(function (type) {
        var serviceConfigTag = serviceConfigTags.findProperty('type', type);
        if (serviceConfigTag) {
          serviceConfigData.pushObject(serviceConfigTag);
        }
      }, this);
      
      if (serviceConfigData.length) {
        //TODO: Remove this delete call when the API supports service_config_version_note
        serviceConfigData.forEach(scd => {
          delete scd.service_config_version_note;
        })

        this.addRequestToAjaxQueue({
          name: 'common.service.create.configs',
          data: {
            serviceName: service.get('serviceName'),
            serviceGroupName: `${service.get('stackName')}-${service.get('stackVersion')}`,
            data: serviceConfigData
          }
        });    
      }
    }, this);
  },

  /**
   * Create and update config groups
   * @method createConfigurationGroups
   */
  createConfigurationGroups: function () {
    var configGroups = this.get('content.configGroups').filterProperty('is_default', false);
    var groupsToDelete = App.router.get(this.get('content.controllerName')).getDBProperty('groupsToDelete');
    if (groupsToDelete && groupsToDelete.length > 0) {
      this.removeInstalledServicesConfigurationGroups(groupsToDelete);
    }
    configGroups.forEach(function (configGroup) {
      if (configGroup.is_for_update || configGroup.is_temporary) {
        this.saveGroup(configGroup.properties, configGroup, this.getServiceConfigNote('', configGroup.service_id));
      }
    }, this);
    App.ServiceConfigGroup.deleteTemporaryRecords();
  },

  /**
   * add request to create config group to queue
   *
   * @param data
   * @method createConfigGroup
   */
  createConfigGroup: function(data) {
    this.addRequestToAjaxQueue({
      name: 'wizard.step8.apply_configuration_groups',
      sender: this,
      data: {
        data: JSON.stringify(data)
      }
    });
  },

  /**
   * add request to update config group to queue
   *
   * @param data {Object}
   * @method updateConfigGroup
   */
  updateConfigGroup: function (data) {
    this.addRequestToAjaxQueue({
      name: 'config_groups.update_config_group',
      sender: this,
      data: {
        id: data.ConfigGroup.id,
        configGroup: data
      }
    });
  },

  /**
   * Delete selected config groups
   * @param {Object[]} groupsToDelete
   * @method removeInstalledServicesConfigurationGroups
   */
  removeInstalledServicesConfigurationGroups: function (groupsToDelete) {
    var self = this;
    groupsToDelete.forEach(function (item) {
      self.deleteConfigurationGroup(Em.Object.create(item));
    });
  },

  /**
   * Selected and installed services
   * @override
   */
  currentServices: function() {
    return this.get('installedServices').concat(this.get('selectedServices'));
  }.property('installedServices.length', 'selectedServices.length'),

  /**
   * Add handling GLUSTREFS properties
   * @param property
   * @returns {*}
   * @override
   */
  formatValueBeforeSave: function(property) {
    if (this.formatGLUSTERFSProperties(Em.get(property, 'filename'))) {
      switch (property.name) {
        case "fs.default.name":
          return this.get('configs').someProperty('name', 'fs_glusterfs_default_name') ?
            this.get('configs').findProperty('name', 'fs_glusterfs_default_name').value : null;
        case "fs.defaultFS":
          return this.get('configs').someProperty('name', 'glusterfs_defaultFS_name') ?
            this.get('configs').findProperty('name', 'glusterfs_defaultFS_name').value : null;
      }
    }
    return this._super(property);
  },

  /**
   * Defines if some GLUSTERFS properties should be changed
   *
   * @param {String} type
   * @returns {boolean}
   */
  formatGLUSTERFSProperties: function(type) {
    return App.config.getConfigTagFromFileName(type) === 'core-site'
      && this.get('installedServices').concat(this.get('selectedServices')).someProperty('serviceName', 'GLUSTERFS');
  },


  /**
   * Create one Alert Notification (if user select this on step7)
   * Only for Install Wizard and stack
   * @method createNotification
   */
  createNotification: function () {
    if (!this.get('isInstaller')) return;
    var miscConfigs = this.get('configs').filterProperty('serviceName', 'MISC'),
      createNotification = miscConfigs.findProperty('name', 'create_notification').value;
    if (createNotification !== 'yes') return;
      var predefinedNotificationConfigNames = require('data/configs/alert_notification').mapProperty('name'),
      configsForNotification = this.get('configs').filterProperty('filename', 'alert_notification');
    var properties = {},
      names = [
        'ambari.dispatch.recipients',
        'mail.smtp.host',
        'mail.smtp.port',
        'mail.smtp.from',
        'mail.smtp.starttls.enable',
        'mail.smtp.startssl.enable'
      ];
    if (miscConfigs.findProperty('name', 'smtp_use_auth').value == 'true') { // yes, it's not converted to boolean
      names.pushObjects(['ambari.dispatch.credential.username', 'ambari.dispatch.credential.password']);
    }

    names.forEach(function (name) {
      properties[name] = miscConfigs.findProperty('name', name).value;
    });

    properties['ambari.dispatch.recipients'] = properties['ambari.dispatch.recipients'].replace(/\s/g, '').split(',');

    configsForNotification.forEach(function (config) {
      if (predefinedNotificationConfigNames.contains(config.name)) return;
      properties[config.name] = config.value;
    });

    var apiObject = {
      AlertTarget: {
        name: 'Initial Notification',
        description: 'Notification created during cluster installing',
        global: true,
        notification_type: 'EMAIL',
        alert_states: ['OK', 'WARNING', 'CRITICAL', 'UNKNOWN'],
        properties: properties
      }
    };
    this.addRequestToAjaxQueue({
      name: 'alerts.create_alert_notification',
      data: {
        urlParams: 'overwrite_existing=true',
        data: apiObject
      }
    });
  },

  /**
   * Should ajax-queue progress bar be displayed
   * @method showLoadingIndicator
   */
  showLoadingIndicator: function () {
    return App.ModalPopup.show({

      header: '',

      showFooter: false,

      showCloseButton: false,

      bodyClass: Em.View.extend({

        templateName: require('templates/wizard/step8/step8_log_popup'),

        controllerBinding: 'App.router.wizardStep8Controller',

        /**
         * Css-property for progress-bar
         * @type {string}
         */
        barWidth: '',
        progressBarClass: 'progress log_popup',

        /**
         * Popup-message
         * @type {string}
         */
        message: '',

        /**
         * Set progress bar width and popup message when ajax-queue requests are processed
         * @method ajaxQueueChangeObs
         */
        ajaxQueueChangeObs: function () {
          var length = this.get('controller.ajaxQueueLength');
          var left = this.get('controller.ajaxRequestsQueue.queue.length');
          this.set('barWidth', 'width: ' + (length - left) / length * 100 + '%;');
          this.set('message', Em.I18n.t('installer.step8.deployPopup.message').format(length - left, length));
        }.observes('controller.ajaxQueueLength', 'controller.ajaxRequestsQueue.queue.length'),

        /**
         * Hide popup when ajax-queue is finished
         * @method autoHide
         */
        autoHide: function () {
          if (this.get('controller.servicesInstalled')) {
            this.get('parentView').hide();
          }
        }.observes('controller.servicesInstalled'),

        ajaxQueueErrorAppears: function () {
          if (this.get('controller.hasErrorOccurred')) {
            this.get('parentView').onClose();
          }
        }.observes('controller.hasErrorOccurred')

      })

    });
  },

  getComponentsForHost: function(host) {
    if(!host.hostComponents) {
      App.router.get('installerController').get('allHosts');
    }
    var componentNameDetail = [];
    host.hostComponents.mapProperty('componentName').forEach(function (componentName) {
      if(componentName === 'CLIENT') {
        this.get('content.clients').mapProperty('component_name').forEach(function (clientComponent) {
          componentNameDetail.push({ name : clientComponent });
        }, this);
        return;
      }
      componentNameDetail.push({ name : componentName });
    }, this);
    return componentNameDetail;
  },

  getPropertyAttributesForConfigType : function(configs) {
    //Currently only looks for final properties, if any
    var finalProperties = configs.filterProperty('isFinal', 'true');
    var propertyAttributes = {};
    finalProperties.forEach(function (finalProperty) {
      propertyAttributes[finalProperty['name']] = "true";
    });
    var finalPropertyMap = {};
    if (!App.isEmptyObject(finalProperties)) {
      finalPropertyMap = {
        "isFinal": propertyAttributes
      };
    }
    return finalPropertyMap;
  },

  getConfigurationDetailsForConfigType: function(configs) {
    var configDetails = {};
    var self = this;
    configs.forEach(function (propertyObj) {
      configDetails[propertyObj['name']] = propertyObj['value'];
    }, this);
    var configurationsDetails = {
      "properties_attributes": self.getPropertyAttributesForConfigType(configs),
      "properties": configDetails
    };
    return configurationsDetails;
  },

  hostInExistingHostGroup: function (newHost, host_groups) {
    var hostGroupMatched = false;
      host_groups.some(function (existingHostGroup) {
        if(!hostGroupMatched) {
        var fqdnInHostGroup =  existingHostGroup.hosts[0].fqdn;
        var componentsInExistingHostGroup = this.getRegisteredHosts().filterProperty('hostName', fqdnInHostGroup)[0].hostComponents;
        if(componentsInExistingHostGroup.length !== newHost.hostComponents.length) {
          return;
        } else {
          var componentMismatch = false;
          componentsInExistingHostGroup.forEach(function (componentInExistingHostGroup, index) {
          if(!componentMismatch) {
            if(!newHost.hostComponents.mapProperty('componentName').includes(componentInExistingHostGroup.componentName)) {
              componentMismatch = true;
            }
          }
          });
          if(!componentMismatch) {
            hostGroupMatched = true;
            existingHostGroup["cardinality"] = parseInt(existingHostGroup["cardinality"]) + 1;
            existingHostGroup.hosts.push({"fqdn" : newHost.hostName});
            return true;
          }
        }
        }
      }, this);
    return hostGroupMatched;
  },

   hostInChildHostGroup: function (presentHostGroup, configGroupName, hostInConfigGroup) {
    return  presentHostGroup['childHostGroups'].some(function (childHostGroup) {
      //Check if childHostGroup name is same as this configgroupname, if yes, update childHostGroup else, compare with other childhostgroups
      if(childHostGroup.configGroupName === configGroupName) {
        childHostGroup.hosts.push( { "fqdn" : hostInConfigGroup } );
        childHostGroup['cardinality'] = childHostGroup['cardinality'] + 1;
        return true;
      }
      });
  },

  /**
   * Confirmation popup before generate blueprint
   */
  generateBlueprintConfirmation: function () {
    var self = this;
    return App.showConfirmationPopup(function () {
      self.generateBlueprint();
      }, Em.I18n.t('installer.step8.generateBlueprint.popup.msg').format(App.clusterStatus.clusterName)
    );
  },

  generateBlueprint: function () {
    console.log("Prepare blueprint for download...");
    var blueprint = {};
    var self = this;
    //service configurations
    var totalConf = [];
    //Add cluster-env
    var clusterEnv = this.get('configs').filterProperty('filename', 'cluster-settings.xml');
    var configurations = {};
    configurations["cluster-env"] = self.getConfigurationDetailsForConfigType(clusterEnv);
    totalConf.push(configurations);
    //Add configurations for selected services
    this.get('selectedServices').forEach(function (service) {
      Object.keys(service.get('configTypes')).forEach(function (type) {
        if (!this.get('serviceConfigTags').someProperty('type', type)) {
          var configs = this.get('configs').filterProperty('filename', App.config.getOriginalFileName(type));
          var configurations = {};
          configurations[type] = self.getConfigurationDetailsForConfigType(configs);
          totalConf.push(configurations);
        }
      }, this);
    }, this);

    var host_groups = [];
    var cluster_template_host_groups = [];
    var counter = 0;

    this.getRegisteredHosts().filterProperty('isInstalled', false).map(function (host) {
      if(self.hostInExistingHostGroup(host, host_groups)) {
        return;
      }
      //Create new host_group if host is not mapped to existing host_groups
      var hostGroupId = "host_group_" + counter;
      var hostListForGroup = [];
      hostListForGroup.push({ "fqdn": host.hostName });
      var hostGroupDetail = {
        "name": hostGroupId,
        "components": self.getComponentsForHost(host),
        "hosts": hostListForGroup,
        "cardinality" : 1
      };
      hostGroupDetail.toJSON = function () {
        var hostGroupDetailResult = _.omit(this, [ "hosts", "childHostGroups" ]);
        hostGroupDetailResult["cardinality"] = this["cardinality"].toString();
        return hostGroupDetailResult;
      };
      host_groups.push(hostGroupDetail);

      var clusterTemplateHostGroupDetail = {
        "name": hostGroupId,
        "hosts": hostListForGroup
      };

      cluster_template_host_groups.push(clusterTemplateHostGroupDetail);
      counter++;
    }, this);

    this.get('content.configGroups').filterProperty("is_default", false).forEach(function (configGroup) {
      if (configGroup.properties.length == 0) {
        return;
      }
      configGroup.hosts.forEach(function (hostInConfigGroup) {
        return host_groups.some(function (presentHostGroup) {
          return presentHostGroup.hosts.some(function (hostInPresentHostGroup, index) {
            if (hostInConfigGroup !== hostInPresentHostGroup.fqdn) {
              return;
            }
            //Check if childHostGroup already created
            if (presentHostGroup['childHostGroups']) {
             if (self.hostInChildHostGroup(presentHostGroup, configGroup.name, hostInConfigGroup)) {
               // Update to remove parentHostGroup as all the hosts are added to childHostGroup/s
               presentHostGroup.hosts.splice(index, 1);
               presentHostGroup["cardinality"] = presentHostGroup['cardinality'] - 1;
               return true;
             }
            }
            //create configuration object
            var hgConfigurations;
            if(presentHostGroup.hosts.length === 1 && presentHostGroup["configurations"]) {
              hgConfigurations = presentHostGroup["configurations"][0];
            } else if (presentHostGroup["configurations"]) { //Deep copy
                hgConfigurations = jQuery.extend(true, {}, presentHostGroup["configurations"][0]);
            } else {
                hgConfigurations = {};
            }
            configGroup.properties.forEach(function (hgProperties) {
              var type = App.config.getConfigTagFromFileName(hgProperties.filename);
              if (!hgConfigurations[type]) {
                hgConfigurations[type] = { properties: {} };
              }
              hgConfigurations[type]['properties'][hgProperties.name] = hgProperties.value;
            });
            var totalHgConf = [];
            totalHgConf.push(hgConfigurations);
            //If only host in presentHostGroup then merge configuration and return
            if (presentHostGroup.hosts.length === 1) {
              //If host_group already has configuration, assigned from previously processed config_group
              if(!presentHostGroup["configurations"]) {
                presentHostGroup["configurations"] = totalHgConf;
              }
              return true;
            }

            //Create new host_group from this host
            var hostGroupId = "host_group_" + counter;
            counter++;
            var hostListForGroup = [];
            hostListForGroup.push({ "fqdn": hostInPresentHostGroup.fqdn });
            var hostGroupDetail = {
              "name": hostGroupId,
              "components": presentHostGroup.components,
              "cardinality": 1,
              "hosts": hostListForGroup,
              "configurations": totalHgConf,
              "configGroupName": configGroup.name
            };
            hostGroupDetail.toJSON = function () {
              var hostGroupDetailResult = _.omit(this, [ "hosts", "configGroupName", "childHostGroups" ]);
              hostGroupDetailResult["cardinality"] = this["cardinality"].toString();
              return hostGroupDetailResult;
            };
            host_groups.push(hostGroupDetail);
            //Update for clustertemplate file
            var clusterTemplateHostGroupDetail = {
              "name": hostGroupId,
              "hosts": hostListForGroup
            };
            cluster_template_host_groups.push(clusterTemplateHostGroupDetail);
            //Add newly created host_group as child to existing host_group
            if (!presentHostGroup['childHostGroups']) {
              presentHostGroup['childHostGroups'] = [];
            }
            presentHostGroup['childHostGroups'].push(hostGroupDetail);
            presentHostGroup.hosts.splice(index, 1);
            presentHostGroup["cardinality"] = presentHostGroup['cardinality'] - 1;
            //return true to indicate that host has been matched
            return true;
          }, this);
        }, this);
      }, this);
    }, this);

    var selectedStack = this.getSelectedStack();
    blueprint = {
        'configurations': totalConf,
        'host_groups': host_groups.filter(function (item) { return item.cardinality > 0; }),
        'Blueprints': {'blueprint_name' : App.clusterStatus.clusterName, 'stack_name':selectedStack.get('stackName'), 'stack_version':selectedStack.get('stackVersion')}
    };
    fileUtils.downloadTextFile(JSON.stringify(blueprint), 'json', 'blueprint.json')

    var cluster_template = {
      "blueprint": App.clusterStatus.clusterName,
      "config_recommendation_strategy" : "NEVER_APPLY",
      "provision_action" : "INSTALL_AND_START",
      "configurations": [],
      "host_groups": cluster_template_host_groups.filter(function (item) { return item.hosts.length > 0; }),
      "Clusters": {'cluster_name': App.clusterStatus.clusterName}
    };
    fileUtils.downloadTextFile(JSON.stringify(cluster_template), 'json', 'clustertemplate.json')
  },

  downloadCSV: function() {
    App.router.get('kerberosWizardStep5Controller').getCSVData(false);
  }
});
