/**
 * 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 blueprintUtils = require('utils/blueprint');
var numberUtils = require('utils/number_utils');
var validationUtils = require('utils/validator');

/**
 * Mixin for assign master-to-host step in wizards
 * Implements basic logic of assign masters page
 * Should be used with controller linked with App.AssignMasterComponentsView
 * @type {Ember.Mixin}
 */
App.AssignMasterComponents = Em.Mixin.create({

  /**
   * Array of master component names to show on the page
   * By default is empty, this means that masters of all selected services should be shown
   * @type {Array}
   */
  mastersToShow: [],

  /**
   * Array of master component names to show on the service config assign master page
   * @type {Array}
   */
  mastersToCreate: [],

  /**
   * Array of master component names to add for install
   * @type {Array}
   */
  mastersToAdd: [],

  /**
   * Array of master component names, that are already installed, but should have ability to change host
   * @type {Array}
   */
  mastersToMove: [],

  /**
   * Array of master component names, that should be addable
   * Are used in HA wizards to add components, that are not addable for other wizards
   * @type {Array}
   */
  mastersAddableInHA: [],

  /**
   * Array of master component names to show 'Current' prefix in label before component name
   * Prefix will be shown only for installed instances
   * @type {Array}
   */
  showCurrentPrefix: [],

  /**
   * Array of master component names to show 'Additional' prefix in label before component name
   * Prefix will be shown only for not installed instances
   * @type {Array}
   */
  showAdditionalPrefix: [],

  /**
   * Array of objects with label and host keys to show specific hosts on the page
   * @type {Array}
   * format:
   * [
   *   {
   *     label: 'Current',
   *     host: 'c6401.ambari.apache.org'
   *   },
   *   {
   *     label: 'Additional',
   *     host: function () {
   *       return 'c6402.ambari.apache.org';
   *     }.property()
   *   }
   * ]
   */
  additionalHostsList: [],

  /**
   * Define whether show already installed masters first
   * @type {Boolean}
   */
  showInstalledMastersFirst: false,

  /**
   * Map of component name to list of hostnames for that component
   * format:
   * {
   *   NAMENODE: [
   *     'c6401.ambari.apache.org'
   *   ],
   *   DATANODE: [
   *     'c6402.ambari.apache.org',
   *     'c6403.ambari.apache.org',
   *   ]
   * }
   * @type {Object}
   */
  recommendedHostsForComponents: {},

  recommendations: null,

  markSavedComponentsAsInstalled: false,

  /**
   * @type {boolean}
   * @default false
   */
  validationInProgress: false,

  /**
   * run validation call which was skipped
   * validation should be always ran after last change
   * @type {boolean}
   * @default false
   */
  runQueuedValidation: false,

  /**
   * Array of <code>servicesMasters</code> objects, that will be shown on the page
   * Are filtered using <code>mastersToShow</code>
   * @type {Array}
   */
  servicesMastersToShow: function () {
    var mastersToShow = this.get('mastersToShow');
    var servicesMasters = this.get('servicesMasters');
    var result = [];
    if (!mastersToShow.length) {
      result = servicesMasters;
    } else {
      mastersToShow.forEach(function (master) {
        result = result.concat(servicesMasters.filterProperty('component_name', master));
      });
    }

    if (this.get('showInstalledMastersFirst')) {
      result = this.sortMasterComponents(result);
    }

    return result;
  }.property('servicesMasters.length', 'mastersToShow.length', 'showInstalledMastersFirst'),

  /**
   * Sort masters, installed masters will be first.
   * @param masters
   * @returns {Array}
   */
  sortMasterComponents: function (masters) {
    return [].concat(masters.filterProperty('isInstalled'), masters.filterProperty('isInstalled', false));
  },

  /**
   * Check if <code>installerWizard</code> used
   * @type {bool}
   */
  isInstallerWizard: Em.computed.equal('content.controllerName', 'installerController'),

  /**
   * Master components which could be assigned to multiple hosts
   * @type {string[]}
   */
  multipleComponents: Em.computed.alias('App.components.multipleMasters'),

  /**
   * Master components which could be assigned to multiple hosts
   * @type {string[]}
   */
  addableComponents: function () {
    return App.get('components.addableMasterInstallerWizard').concat(this.get('mastersAddableInHA')).uniq();
  }.property('App.components.addableMasterInstallerWizard', 'mastersAddableInHA'),

  /**
   * Define state for submit button
   * @type {bool}
   */
  submitDisabled: false,

  /**
   * Is Submit-click processing now
   * @type {bool}
   */
  submitButtonClicked: false,

  /**
   * Either use or not use server validation in this controller
   * @type {bool}
   */
  useServerValidation: true,

  /**
   * Trigger for executing host names check for components
   * Should de "triggered" when host changed for some component and when new multiple component is added/removed
   * @type {bool}
   */
  hostNameCheckTrigger: false,

  /**
   * List of hosts
   * @type {Array}
   */
  hosts: [],

  /**
   * Name of multiple component which host name was changed last
   * @type {Object|null}
   */
  componentToRebalance: null,

  /**
   * Name of component which host was changed last
   * @type {string}
   */
  lastChangedComponent: null,

  /**
   * Flag for rebalance multiple components
   * @type {number}
   */
  rebalanceComponentHostsCounter: 0,

  /**
   * @type {Ember.Enumerable}
   */
  servicesMasters: [],

  /**
   * @type {Ember.Enumerable}
   */
  selectedServicesMasters: [],

  /**
   * Is hosts data loaded
   * @type {bool}
   */
  isHostsLoaded: false,

  /**
   * Are recommendations loaded
   * @type {bool}
   */
  isRecommendationsLoaded: false,

  /**
   * Is data for current step loaded
   * @type {bool}
   */
  isLoaded: Em.computed.and('isHostsLoaded', 'isRecommendationsLoaded'),

  /**
   * Validation error messages which don't related with any master
   */
  generalErrorMessages: [],

  /**
   * Validation warning messages which don't related with any master
   */
  generalWarningMessages: [],

  /**
   * Is masters-hosts layout initial one
   * @type {bool}
   */
  isInitialLayout: true,

  /**
   * Is back from the next step
   * @type {bool}
   */
  backFromNextStep: false,

  /**
   * true if any error exists
   */
  anyError: function() {
    return this.get('servicesMasters').some(function(m) { return m.get('errorMessage'); }) || this.get('generalErrorMessages').some(function(m) { return m; });
  }.property('servicesMasters.@each.errorMessage', 'generalErrorMessages'),

  /**
   * true if any warning exists
   */
  anyWarning: function() {
    return this.get('servicesMasters').some(function(m) { return m.get('warnMessage'); }) || this.get('generalWarningMessages').some(function(m) { return m; });
  }.property('servicesMasters.@each.warnMessage', 'generalWarningMessages'),

  /**
   * Clear loaded recommendations
   */
  clearRecommendations: function() {
    if (this.get('content.recommendations')) {
      this.set('content.recommendations', null);
    }
    if (this.get('recommendations')) {
      this.set('recommendations', null);
    }
  },

  /**
   * List of host with assigned masters
   * Format:
   * <code>
   *   [
   *     {
   *       host_name: '',
   *       hostInfo: {},
   *       masterServices: [],
   *       masterServicesToDisplay: [] // used only in template
   *    },
   *    ....
   *   ]
   * </code>
   * @type {Ember.Enumerable}
   */
  masterHostMapping: function () {
    var mapping = [], mappingObject, mappedHosts, hostObj;
    //get the unique assigned hosts and find the master services assigned to them
    mappedHosts = this.get("selectedServicesMasters").mapProperty("selectedHost").uniq();
    mappedHosts.forEach(function (item) {
      hostObj = this.get("hosts").findProperty("host_name", item);
      // User may input invalid host name (this is handled in hostname checker). Here we just skip it
      if (!hostObj) return;
      var masterServices = this.get("selectedServicesMasters").filterProperty("selectedHost", item),
          masterServicesToDisplay = [];
      masterServices.mapProperty('display_name').uniq().forEach(function (n) {
        masterServicesToDisplay.pushObject(masterServices.findProperty('display_name', n));
      });
      mappingObject = Em.Object.create({
        host_name: item,
        hostInfo: hostObj.host_info,
        masterServices: masterServices,
        masterServicesToDisplay: masterServicesToDisplay
      });

      mapping.pushObject(mappingObject);
    }, this);

    return mapping.sortProperty('host_name');
  }.property('selectedServicesMasters.@each.selectedHost', 'selectedServicesMasters.@each.isHostNameValid', 'isLoaded'),

  /**
   * Count of hosts without masters
   * @type {number}
   */
  remainingHosts: function () {
    if (this.get('content.controllerName') === 'installerController') {
      return 0;
    } else {
      return (this.get("hosts.length") - this.get("masterHostMapping.length"));
    }
  }.property('masterHostMapping.length', 'selectedServicesMasters.@each.selectedHost'),

  /**
   * Update submit button status
   * @method updateIsSubmitDisabled
   */
  updateIsSubmitDisabled: function () {

    if (this.thereIsNoMasters()) {
      return false;
    }

    var isSubmitDisabled = this.get('servicesMasters').someProperty('isHostNameValid', false);

    if (this.get('useServerValidation')) {
      this.set('submitDisabled', true);

      if (this.get('servicesMasters').length === 0) {
        return;
      }

      if (!isSubmitDisabled) {
        if (!this.get('isInitialLayout')) {
          this.clearRecommendations(); // reset previous recommendations
        } else {
          this.set('isInitialLayout', false);
        }
        this.recommendAndValidate();
      }
    } else {
      isSubmitDisabled = isSubmitDisabled || !this.customClientSideValidation();
      this.set('submitDisabled', isSubmitDisabled);
      return isSubmitDisabled;
    }
  }.observes('servicesMasters.@each.selectedHost'),

  /**
   * Function to validate master-to-host assignments
   * Should be defined in controller
   * @returns {boolean}
   */
  customClientSideValidation: function () {
    return true;
  },

  /**
   * Send AJAX request to validate current host layout
   * @param blueprint - blueprint for validation (can be with/withour slave/client components)
   */
  validate: function(blueprint, callback) {
    var self = this;

    var selectedServices = App.StackService.find().filterProperty('isSelected').mapProperty('serviceName');
    var installedServices = App.StackService.find().filterProperty('isInstalled').mapProperty('serviceName');
    var services = installedServices.concat(selectedServices).uniq();

    var hostNames = self.get('hosts').mapProperty('host_name');

    App.ajax.send({
      name: 'config.validations',
      sender: self,
      data: {
        stackVersionUrl: App.get('stackVersionURL'),
        hosts: hostNames,
        services: services,
        validate: 'host_groups',
        recommendations: blueprint
      },
      success: 'updateValidationsSuccessCallback',
      error: 'updateValidationsErrorCallback'
    }).then(function() {
          if (callback) {
            callback();
          }
        }
    );
  },

  /**
   * Success-callback for validations request
   * @param {object} data
   * @method updateValidationsSuccessCallback
   */
  updateValidationsSuccessCallback: function (data) {
    var self = this;

    var generalErrorMessages = [];
    var generalWarningMessages = [];
    this.get('servicesMasters').setEach('warnMessage', null);
    this.get('servicesMasters').setEach('errorMessage', null);
    var anyErrors = false;

    var validationData = validationUtils.filterNotInstalledComponents(data);
    validationData.filterProperty('type', 'host-component').forEach(function(item) {
      var master = self.get('servicesMasters').find(function(m) {
        return m.component_name === item['component-name'] && m.selectedHost === item.host;
      });
      if (master) {
        if (item.level === 'ERROR') {
          anyErrors = true;
          master.set('errorMessage', item.message);
        } else if (item.level === 'WARN') {
          master.set('warnMessage', item.message);
        }
      }
    });

    this.set('generalErrorMessages', generalErrorMessages);
    this.set('generalWarningMessages', generalWarningMessages);

    // use this.set('submitDisabled', anyErrors); is validation results should block next button
    // It's because showValidationIssuesAcceptBox allow use accept validation issues and continue
    this.set('submitDisabled', false); //this.set('submitDisabled', anyErrors);
  },

  /**
   * Error-callback for validations request
   * @param {object} jqXHR
   * @param {object} ajaxOptions
   * @param {string} error
   * @param {object} opt
   * @method updateValidationsErrorCallback
   */
  updateValidationsErrorCallback: function (jqXHR, ajaxOptions, error, opt) {
  },

  /**
   * Composes selected values of comboboxes into master blueprint + merge it with currently installed slave blueprint
   */
  getCurrentBlueprint: function() {
    var self = this;

    var res = {
      blueprint: { host_groups: [] },
      blueprint_cluster_binding: { host_groups: [] }
    };

    var mapping = self.get('masterHostMapping');

    mapping.forEach(function(item, i) {
      var group_name = 'host-group-' + (i+1);

      var host_group = {
        name: group_name,
        components: item.masterServices.map(function(master) {
          return { name: master.component_name };
        })
      };

      var binding = {
        name: group_name,
        hosts: [ { fqdn: item.host_name } ]
      };

      res.blueprint.host_groups.push(host_group);
      res.blueprint_cluster_binding.host_groups.push(binding);
    });

    return blueprintUtils.mergeBlueprints(res, self.getCurrentSlaveBlueprint());
  },

  /**
   * Clear controller data (hosts, masters etc)
   * @method clearStep
   */
  clearStep: function () {
    this.setProperties({
      hosts: [],
      isHostsLoaded: false,
      isRecommendationsLoaded: false,
      backFromNextStep: false,
      selectedServicesMasters: [],
      servicesMasters: []
    });
    App.StackServiceComponent.find().forEach(function (stackComponent) {
      stackComponent.set('serviceComponentId', 1);
    }, this);

  },

  clearStepOnExit: function () {
    this.clearStep();
  },

  /**
   * Load controller data (hosts, host components etc)
   * @method loadStep
   */
  loadStep: function () {
    var self = this;
    this.clearStep();
    if (this._additionalClearSteps) {
      this._additionalClearSteps();
    }
    this.renderHostInfo().done(function () {
      //when returning from step Assign Slaves and Clients, recommendations are already available
      //set the flag so that recommendations AJAX call is not made unnecessarily
      if (self.get('recommendations')) {
        self.set('backFromNextStep', true);
      }
      self.loadComponentsRecommendationsFromServer(self.loadStepCallback);
    });
  },

  /**
   * Callback after load controller data (hosts, host components etc)
   * @method loadStepCallback
   */
  loadStepCallback: function(components, self) {
    self.renderComponents(components);

    self.get('addableComponents').forEach(function (componentName) {
      self.updateComponent(componentName);
    }, self);
    self.set('isRecommendationsLoaded', true);
    if (self.thereIsNoMasters() && !self.get('mastersToCreate').length) {
      App.router.send('next');
    }
  },

  /**
   * Returns true if there is no new master components which need assigment to host
   */
  thereIsNoMasters: function() {
    return !this.get("selectedServicesMasters").filterProperty('isInstalled', false).length;
  },

  /**
   * Used to set showAddControl flag for installer wizard
   * @method updateComponent
   */
  updateComponent: function (componentName) {
    var component = this.last(componentName);
    if (!component) {
      return;
    }

    var showControl = !App.StackServiceComponent.find().findProperty('componentName', componentName).get('stackService').get('isInstalled')
        || this.get('mastersAddableInHA').contains(componentName);

    if (showControl) {
      var mastersLength = this.get("selectedServicesMasters").filterProperty("component_name", componentName).length;
      if (mastersLength < this.getMaxNumberOfMasters(componentName)) {
        component.set('showAddControl', true);
      } else {
        component.set('showRemoveControl', mastersLength != 1);
      }
    }
  },

  /**
   * Count max number of instances for masters <code>componentName</code>, according to their cardinality and number of hosts
   * @param componentName
   * @returns {Number}
   */
  getMaxNumberOfMasters: function (componentName) {
    var maxByCardinality = App.StackServiceComponent.find().findProperty('componentName', componentName).get('maxToInstall');
    var hostsNumber = this.get("hosts.length");
    return Math.min(maxByCardinality, hostsNumber);
  },

  /**
   * Load active host list to <code>hosts</code> variable
   * @method renderHostInfo
   */
  renderHostInfo: function () {
    var self = this;
    var isInstaller = (this.get('wizardController.name') === 'installerController' || this.get('content.controllerName') === 'installerController');
    return App.ajax.send({
      name: isInstaller ? 'hosts.info.install' : 'hosts.high_availability.wizard',
      sender: this,
      data: {
        hostNames: isInstaller ? this.getHosts().join() : null
      }
    }).success(function(data) {
      self.loadWizardHostsSuccessCallback(data)
    });
  },

  loadWizardHostsSuccessCallback: function (data) {
    var hostInfo = this.get('content.hosts'),
      result = [];
    data.items.forEach(function (host) {
      var hostName = host.Hosts.host_name,
        _host = hostInfo[hostName],
        cpu = host.Hosts.cpu_count,
        memory = host.Hosts.total_mem.toFixed(2);
      if (_host.bootStatus === 'REGISTERED') {
        result.push(Em.Object.create({
          host_name: hostName,
          cpu: cpu,
          memory: memory,
          disk_info: host.Hosts.disk_info,
          maintenance_state: host.Hosts.maintenance_state,
          isInstalled: _host.isInstalled,
          host_info: Em.I18n.t('installer.step5.hostInfo').fmt(hostName, numberUtils.bytesToSize(memory, 1, 'parseFloat', 1024), cpu)
        }));
      }
    }, this);
    this.set('hosts', result);
    this.sortHosts(this.get('hosts'));
    this.set('isHostsLoaded', true);
  },

  /**
   * Sort list of host-objects by properties (memory - desc, cpu - desc, hostname - asc)
   * @param {object[]} hosts
   */
  sortHosts: function (hosts) {
    hosts.sort(function (a, b) {
      if (a.get('memory') == b.get('memory')) {
        if (a.get('cpu') == b.get('cpu')) {
          return a.get('host_name').localeCompare(b.get('host_name')); // hostname asc
        }
        return b.get('cpu') - a.get('cpu'); // cores desc
      }
      return b.get('memory') - a.get('memory'); // ram desc
    });
  },

  /**
   * Get recommendations info from API
   * @param {function}callback
   * @param {boolean} includeMasters
   * @method loadComponentsRecommendationsFromServer
   */
  loadComponentsRecommendationsFromServer: function(callback, includeMasters) {
    var self = this;

    //when returning from step Assign Slaves and Clients, backFromNextStep will be true
    if (this.get('recommendations') && this.get('backFromNextStep')) {
      // Don't do AJAX call if recommendations has been already received
      // But if user returns to previous step (selecting services), stored recommendations will be cleared in routers' next handler and AJAX call will be made again
      callback(self.createComponentInstallationObjects(), self);
    }
    else {
      var selectedServices = App.StackService.find().filterProperty('isSelected').mapProperty('serviceName');
      var installedServices = App.StackService.find().filterProperty('isInstalled').mapProperty('serviceName');
      var services = installedServices.concat(selectedServices).uniq();

      var hostNames = self.getHosts();

      var data = {
        stackVersionUrl: App.get('stackVersionURL'),
        hosts: hostNames,
        services: services,
        recommend: 'host_groups'
      };

      if (includeMasters) {
        // Made partial recommendation request for reflect in blueprint host-layout changes which were made by user in UI
        data.recommendations = self.getCurrentBlueprint();
      }
      else
        if (!self.get('isInstallerWizard')) {
          data.recommendations = self.getCurrentMasterSlaveBlueprint();
        }

      return App.ajax.send({
        name: 'wizard.loadrecommendations',
        sender: self,
        data: data,
        success: 'loadRecommendationsSuccessCallback',
        error: 'loadRecommendationsErrorCallback'
      }).then(function () {
          callback(self.createComponentInstallationObjects(), self);
        });
    }
  },

  /**
   * Create components for displaying component-host comboboxes in UI assign dialog
   * expects content.recommendations will be filled with recommendations API call result
   * @return {Object[]}
   */
  createComponentInstallationObjects: function() {
    var stackMasterComponentsMap = {},
        masterHosts = this.get('content.masterComponentHosts') || this.get('masterComponentHosts'), //saved to local storage info
        servicesToAdd = (this.get('content.services')|| []).filterProperty('isSelected').filterProperty('isInstalled', false).mapProperty('serviceName'),
        recommendations = this.get('recommendations'),
        resultComponents = [],
        multipleComponentHasBeenAdded = {},
        hostGroupsMap = {};

    App.StackServiceComponent.find().forEach(function(component) {
      var isMasterCreateOnConfig = this.get('mastersToCreate').contains(component.get('componentName'));
      if (this.get('isInstallerWizard') && (component.get('isShownOnInstallerAssignMasterPage') || isMasterCreateOnConfig) ) {
        stackMasterComponentsMap[component.get('componentName')] = component;
      } else if (component.get('isShownOnAddServiceAssignMasterPage') || this.get('mastersToShow').contains(component.get('componentName')) || isMasterCreateOnConfig) {
        stackMasterComponentsMap[component.get('componentName')] = component;
      }
    }, this);

    recommendations.blueprint_cluster_binding.host_groups.forEach(function(group) {
      hostGroupsMap[group.name] = group;
    });

    recommendations.blueprint.host_groups.forEach(function(host_group) {
      var hosts = hostGroupsMap[host_group.name] ? hostGroupsMap[host_group.name].hosts : [];

      hosts.forEach(function(host) {
        host_group.components.forEach(function(component) {
          var willBeDisplayed = true;
          var stackMasterComponent = stackMasterComponentsMap[component.name];
          if (stackMasterComponent) {
            var isMasterCreateOnConfig = this.get('mastersToCreate').contains(component.name);
            // If service is already installed and not being added as a new service then render on UI only those master components
            // that have already installed hostComponents.
            // NOTE: On upgrade there might be a prior installed service with non-installed newly introduced serviceComponent
            if (!servicesToAdd.contains(stackMasterComponent.get('serviceName')) && !isMasterCreateOnConfig) {
              willBeDisplayed = masterHosts.someProperty('component', component.name);
            }

            if (willBeDisplayed) {
              var savedComponents = masterHosts.filterProperty('component', component.name);

              if (this.get('multipleComponents').contains(component.name) && savedComponents.length > 0) {
                if (!multipleComponentHasBeenAdded[component.name]) {
                  multipleComponentHasBeenAdded[component.name] = true;

                  savedComponents.forEach(function(saved) {
                    resultComponents.push(this.createComponentInstallationObject(stackMasterComponent, host.fqdn.toLowerCase(), saved));
                  }, this);
                }
              } else {
                var savedComponent = masterHosts.findProperty('component', component.name);
                resultComponents.push(this.createComponentInstallationObject(stackMasterComponent, host.fqdn.toLowerCase(), savedComponent));
              }
            }
          }
        }, this);
      }, this);
    }, this);
    return resultComponents;
  },

  /**
   * Create component for displaying component-host comboboxes in UI assign dialog
   * @param fullComponent - full component description
   * @param hostName - host fqdn where component will be installed
   * @param savedComponent - the same object which function returns but created before
   * @return {Object}
   */
  createComponentInstallationObject: function(fullComponent, hostName, savedComponent) {
    var componentName = fullComponent.get('componentName');

    var componentObj = {};
    componentObj.component_name = componentName;
    componentObj.display_name = App.format.role(fullComponent.get('componentName'), false);
    componentObj.serviceId = fullComponent.get('serviceName');
    componentObj.isServiceCoHost = App.StackServiceComponent.find().findProperty('componentName', componentName).get('isCoHostedComponent') && !this.get('mastersToMove').contains(componentName);
    componentObj.selectedHost = savedComponent ? savedComponent.hostName : hostName;
    componentObj.isInstalled = savedComponent ? savedComponent.isInstalled || (this.get('markSavedComponentsAsInstalled') && !this.get('mastersToCreate').contains(fullComponent.get('componentName'))) : false;
    return componentObj;
  },

  /**
   * Success-callback for recommendations request
   * @param {object} data
   * @method loadRecommendationsSuccessCallback
   */
  loadRecommendationsSuccessCallback: function (data) {
    var recommendations = data.resources[0].recommendations;
    this.set('recommendations', recommendations);
    if (this.get('content.controllerName')) {
      this.set('content.recommendations', recommendations);
    }

    var recommendedHostsForComponent = {};
    var hostsForHostGroup = {};

    recommendations.blueprint_cluster_binding.host_groups.forEach(function(hostGroup) {
      hostsForHostGroup[hostGroup.name] = hostGroup.hosts.mapProperty('fqdn');
    });

    recommendations.blueprint.host_groups.forEach(function (hostGroup) {
      var components = hostGroup.components.mapProperty('name');
      components.forEach(function (componentName) {
        var hostList = recommendedHostsForComponent[componentName] || [];
        var hostNames = hostsForHostGroup[hostGroup.name] || [];
        hostList.pushObjects(hostNames);
        recommendedHostsForComponent[componentName] = hostList;
      });
    });

    this.set('recommendedHostsForComponents', recommendedHostsForComponent);
    if (this.get('content.controllerName')) {
      this.set('content.recommendedHostsForComponents', recommendedHostsForComponent);
    }
  },

  /**
   * Error-callback for recommendations request
   * @param {object} jqXHR
   * @param {object} ajaxOptions
   * @param {string} error
   * @param {object} opt
   * @method loadRecommendationsErrorCallback
   */
  loadRecommendationsErrorCallback: function (jqXHR, ajaxOptions, error, opt) {
    App.ajax.defaultErrorHandler(jqXHR, opt.url, opt.type, jqXHR.status);
  },

  /**
   * Put master components to <code>selectedServicesMasters</code>, which will be automatically rendered in template
   * @param {Ember.Enumerable} masterComponents
   * @method renderComponents
   */
  renderComponents: function (masterComponents) {
    var installedServices = App.StackService.find().filterProperty('isSelected').filterProperty('isInstalled', false).mapProperty('serviceName'); //list of shown services
    var result = [];
    var serviceComponentId, previousComponentName;

    this.addNewMasters(masterComponents);

    masterComponents.forEach(function (item) {
      var masterComponent = App.StackServiceComponent.find().findProperty('componentName', item.component_name);
      var componentObj = Em.Object.create(item);
      var showRemoveControl;
      if (masterComponent.get('isMasterWithMultipleInstances')) {
        showRemoveControl = installedServices.contains(masterComponent.get('stackService.serviceName')) &&
            (masterComponents.filterProperty('component_name', item.component_name).length > 1);
        previousComponentName = item.component_name;
        componentObj.set('serviceComponentId', result.filterProperty('component_name', item.component_name).length + 1);
        componentObj.set("showRemoveControl", showRemoveControl);
      }
      componentObj.set('isHostNameValid', true);
      componentObj.set('showCurrentPrefix', this.get('showCurrentPrefix').contains(item.component_name) && item.isInstalled);
      componentObj.set('showAdditionalPrefix', this.get('showAdditionalPrefix').contains(item.component_name) && !item.isInstalled);
      if (this.get('mastersToMove').contains(item.component_name)) {
        componentObj.set('isInstalled', false);
      }

      result.push(componentObj);
    }, this);
    result = this.sortComponentsByServiceName(result);
    this.set("selectedServicesMasters", result);
    this.set('servicesMasters', result);
  },

  /**
   * Add new master components from <code>mastersToAdd</code> list
   * @param masterComponents
   * @returns {masterComponents[]}
   */
  addNewMasters: function (masterComponents) {
    this.get('mastersToAdd').forEach(function (masterName, index, mastersToAdd) {
      var toBeAddedNumber = mastersToAdd.filter(function (name) {
          return name === masterName;
        }).length,
        alreadyAddedNumber = masterComponents.filterProperty('component_name', masterName).rejectProperty('isInstalled').length;
      if (toBeAddedNumber > alreadyAddedNumber) {
        var hostName = this.getHostForMaster(masterName, masterComponents),
          serviceName = this.getServiceByMaster(masterName);
        masterComponents.push(this.createComponentInstallationObject(
          Em.Object.create({
            componentName: masterName,
            serviceName: serviceName
          }),
          hostName
        ));
      }
    }, this);
    return masterComponents;
  },

  /**
   * Find available host for master and return it
   * If there is no available hosts returns false
   * @param master
   * @param allMasters
   * @returns {*}
   */
  getHostForMaster: function (master, allMasters) {
    var masterHostList = [];

    allMasters.forEach(function (component) {
      if (component.component_name === master) {
        masterHostList.push(component.selectedHost);
      }
    });

    var recommendedHostsForMaster = this.get('recommendedHostsForComponents')[master] || [];
    for (var k = 0; k < recommendedHostsForMaster.length; k++) {
      if(!masterHostList.contains(recommendedHostsForMaster[k])) {
        return recommendedHostsForMaster[k];
      }
    }

    var usedHosts = allMasters.filterProperty('component_name', master).mapProperty('selectedHost');
    var allHosts = this.get('hosts');
    for (var i = 0; i < allHosts.length; i++) {
      if (!usedHosts.contains(allHosts[i].get('host_name'))) {
        return allHosts[i].get('host_name');
      }
    }

    return false;
  },

  /**
   * Find serviceName for master by it's componentName
   * @param master
   * @returns {*}
   */
  getServiceByMaster: function (master) {
    return App.StackServiceComponent.find().findProperty('componentName', master).get('serviceName');
  },

  /**
   * Sort components by their service (using <code>App.StackService.displayOrder</code>)
   * Services not in App.StackService.displayOrder are moved to the end of the list
   *
   * @param components
   * @returns {*}
   */
  sortComponentsByServiceName: function(components) {
    var displayOrder = App.StackService.displayOrder;
    var componentsOrderForService = App.StackService.componentsOrderForService;
    var indexForUnordered = Math.max(displayOrder.length, components.length);
    return components.sort(function (a, b) {
      if(a.serviceId === b.serviceId && a.serviceId in componentsOrderForService)
        return componentsOrderForService[a.serviceId].indexOf(a.component_name) - componentsOrderForService[b.serviceId].indexOf(b.component_name);
      var aValue = displayOrder.indexOf(a.serviceId) != -1 ? displayOrder.indexOf(a.serviceId) : indexForUnordered;
      var bValue = displayOrder.indexOf(b.serviceId) != -1 ? displayOrder.indexOf(b.serviceId) : indexForUnordered;
      return aValue - bValue;
    });
  },
  /**
   * Update dependent co-hosted components according to the change in the component host
   * @method updateCoHosts
   */
  updateCoHosts: function () {
    var components = App.StackServiceComponent.find().filterProperty('isOtherComponentCoHosted');
    var selectedServicesMasters = this.get('selectedServicesMasters');
    components.forEach(function (component) {
      var componentName = component.get('componentName');
      var hostComponent = selectedServicesMasters.findProperty('component_name', componentName);
      var dependentCoHosts = component.get('coHostedComponents');
      dependentCoHosts.forEach(function (coHostedComponent) {
        var dependentHostComponent = selectedServicesMasters.findProperty('component_name', coHostedComponent);
        if (!this.get('mastersToMove').contains(coHostedComponent) && hostComponent && dependentHostComponent) dependentHostComponent.set('selectedHost', hostComponent.get('selectedHost'));
      }, this);
    }, this);
  }.observes('selectedServicesMasters.@each.selectedHost'),


  /**
   * On change callback for inputs
   * @param {string} componentName
   * @param {string} selectedHost
   * @param {number} serviceComponentId
   * @method assignHostToMaster
   */
  assignHostToMaster: function (componentName, selectedHost, serviceComponentId) {
    var flag = this.isHostNameValid(componentName, selectedHost);
    var component;
    this.updateIsHostNameValidFlag(componentName, serviceComponentId, flag);
    if (serviceComponentId) {
      component = this.get('selectedServicesMasters').filterProperty('component_name', componentName).findProperty("serviceComponentId", serviceComponentId);
      if (component) component.set("selectedHost", selectedHost);
    }
    else {
      this.get('selectedServicesMasters').findProperty("component_name", componentName).set("selectedHost", selectedHost);
    }
  },

  /**
   * Determines if hostName is valid for component:
   * <ul>
   *  <li>host name shouldn't be empty</li>
   *  <li>host should exist</li>
   *  <li>if host installed maintenance state should be 'OFF'</li>
   *  <li>host should have only one component with <code>componentName</code></li>
   * </ul>
   * @param {string} componentName
   * @param {string} selectedHost
   * @returns {boolean} true - valid, false - invalid
   * @method isHostNameValid
   */
  isHostNameValid: function (componentName, selectedHost) {
    return (selectedHost.trim() !== '') &&
      (this.get('hosts').filter(function(host) {
        return host.host_name === selectedHost && (!host.isInstalled || host.maintenance_state === 'OFF');
      }).length > 0) &&
      (this.get('selectedServicesMasters').
        filterProperty('component_name', componentName).
        mapProperty('selectedHost').
        filter(function (h) {
          return h === selectedHost;
        }).length <= 1);
  },

  /**
   * Update <code>isHostNameValid</code> property with <code>flag</code> value
   * for component with name <code>componentName</code> and
   * <code>serviceComponentId</code>-property equal to <code>serviceComponentId</code>-parameter value
   * @param {string} componentName
   * @param {number} serviceComponentId
   * @param {bool} flag
   * @method updateIsHostNameValidFlag
   */
  updateIsHostNameValidFlag: function (componentName, serviceComponentId, flag) {
    var component;
    if (componentName) {
      if (serviceComponentId) {
        component = this.get('selectedServicesMasters').filterProperty('component_name', componentName).findProperty("serviceComponentId", serviceComponentId);
      } else {
        component = this.get('selectedServicesMasters').findProperty("component_name", componentName);
      }
      if (component) {
        component.set("isHostNameValid", flag);
        component.set("errorMessage", flag ? null : Em.I18n.t('installer.step5.error.host.invalid'));
      }
    }
  },

  /**
   * Returns last component of selected type
   * @param {string} componentName
   * @return {Em.Object|null}
   * @method last
   */
  last: function (componentName) {
    return this.get("selectedServicesMasters").filterProperty("component_name", componentName).get("lastObject");
  },

  /**
   * Add new component to ZooKeeper Server and Hbase master
   * @param {string} componentName
   * @return {bool} true - added, false - not added
   * @method addComponent
   */
  addComponent: function (componentName) {
    /*
     * Logic: If ZooKeeper or Hbase service is selected then there can be
     * minimum 1 ZooKeeper or Hbase master in total, and
     * maximum 1 ZooKeeper or Hbase on every host
     */

    var maxNumMasters = this.getMaxNumberOfMasters(componentName),
        currentMasters = this.get("selectedServicesMasters").filterProperty("component_name", componentName).sortProperty('serviceComponentId'),
        newMaster = null,
        masterHosts = null,
        suggestedHost = null,
        i = 0,
        lastMaster = null;

    if (!currentMasters.length) {
      return false;
    }

    if (currentMasters.get("length") < maxNumMasters) {

      currentMasters.set("lastObject.showAddControl", false);
      currentMasters.set("lastObject.showRemoveControl", true);

      //create a new master component host based on an existing one
      newMaster = Em.Object.create({});
      lastMaster = currentMasters.get("lastObject");
      newMaster.set("display_name", lastMaster.get("display_name"));
      newMaster.set("component_name", lastMaster.get("component_name"));
      newMaster.set("selectedHost", lastMaster.get("selectedHost"));
      newMaster.set("serviceId", lastMaster.get("serviceId"));
      newMaster.set("isInstalled", false);
      newMaster.set('showAdditionalPrefix', this.get('showAdditionalPrefix').contains(lastMaster.get("component_name")));

      if (currentMasters.get("length") === (maxNumMasters - 1)) {
        newMaster.set("showAddControl", false);
      } else {
        newMaster.set("showAddControl", true);
      }
      newMaster.set("showRemoveControl", true);

      //get recommended host for the new Zookeeper server
      masterHosts = currentMasters.mapProperty("selectedHost").uniq();

      for (i = 0; i < this.get("hosts.length"); i++) {
        if (!(masterHosts.contains(this.get("hosts")[i].get("host_name")))) {
          suggestedHost = this.get("hosts")[i].get("host_name");
          break;
        }
      }

      newMaster.set("selectedHost", suggestedHost);
      newMaster.set("serviceComponentId", (currentMasters.get("lastObject.serviceComponentId") + 1));

      this.get("selectedServicesMasters").insertAt(this.get("selectedServicesMasters").indexOf(lastMaster) + 1, newMaster);

      this.setProperties({
        componentToRebalance: componentName,
        lastChangedComponent: componentName
      });
      this.incrementProperty('rebalanceComponentHostsCounter');
      this.toggleProperty('hostNameCheckTrigger');
      return true;
    }
    return false;//if no more zookeepers can be added
  },

  /**
   * Remove component from ZooKeeper server or Hbase Master
   * @param {string} componentName
   * @param {number} serviceComponentId
   * @return {bool} true - removed, false - no
   * @method removeComponent
   */
  removeComponent: function (componentName, serviceComponentId) {
    var currentMasters = this.get("selectedServicesMasters").filterProperty("component_name", componentName);

    //work only if the multiple master service is selected in previous step
    if (currentMasters.length <= 1) {
      return false;
    }

    this.get("selectedServicesMasters").removeAt(this.get("selectedServicesMasters").indexOf(currentMasters.findProperty("serviceComponentId", serviceComponentId)));

    currentMasters = this.get("selectedServicesMasters").filterProperty("component_name", componentName);
    if (currentMasters.get("length") < this.getMaxNumberOfMasters(componentName)) {
      currentMasters.set("lastObject.showAddControl", true);
    }

    if (currentMasters.filterProperty('isInstalled', false).get("length") === 1) {
      currentMasters.set("lastObject.showRemoveControl", false);
    }

    this.setProperties({
      componentToRebalance: componentName,
      lastChangedComponent: componentName
    });
    this.incrementProperty('rebalanceComponentHostsCounter');
    this.toggleProperty('hostNameCheckTrigger');
    return true;
  },

  recommendAndValidate: function(callback) {
    var self = this;

    if (this.get('validationInProgress')) {
      this.set('runQueuedValidation', true);
      return;
    }

    this.set('validationInProgress', true);

    // load recommendations with partial request
    self.loadComponentsRecommendationsFromServer(function() {
      // For validation use latest received recommendations because it contains current master layout and recommended slave/client layout
      self.validate(self.get('recommendations'), function() {
        if (callback) {
          callback();
        }
        self.set('validationInProgress', false);
        if (self.get('runQueuedValidation')) {
          self.set('runQueuedValidation', false);
          self.recommendAndValidate(callback);
        }
      });
    }, true);
  },

  _goNextStepIfValid: function () {
    if (!this.get('submitDisabled')) {
      App.router.send('next');
    }else{
      App.set('router.nextBtnClickInProgress', false);
    }
  },

  nextButtonDisabled: Em.computed.or('App.router.btnClickInProgress', 'submitDisabled', 'validationInProgress', '!isLoaded'),

  /**
   * Submit button click handler
   * Disable 'Next' button while it is already under process. (using Router's property 'nextBtnClickInProgress')
   * @method submit
   */
  submit: function () {
    var self = this;
    if (this.get('submitDisabled')) {
      return;
    }
    if (!this.get('submitButtonClicked') && !App.get('router.nextBtnClickInProgress')) {
      this.set('submitButtonClicked', true);
      App.router.set('nextBtnClickInProgress', true);

      if (this.get('useServerValidation')) {
        self.recommendAndValidate(function () {
          self.showValidationIssuesAcceptBox(self._goNextStepIfValid.bind(self));
        });
      }
      else {
        this.updateIsSubmitDisabled();
        this._goNextStepIfValid();
        this.set('submitButtonClicked', false);
      }
    }
  },

  /**
   * In case of any validation issues shows accept dialog box for user which allow cancel and fix issues or continue anyway
   * @method showValidationIssuesAcceptBox
   */
  showValidationIssuesAcceptBox: function(callback) {
    var self = this;

    // If there are no warnings and no errors, return
    if (!self.get('anyWarning') && !self.get('anyError')) {
      callback();
      self.set('submitButtonClicked', false);
      return;
    }

    App.ModalPopup.show({
      primary: Em.I18n.t('common.continueAnyway'),
      header: Em.I18n.t('installer.step5.validationIssuesAttention.header'),
      body: Em.I18n.t('installer.step5.validationIssuesAttention'),
      onPrimary: function () {
        this._super();
        callback();
        self.set('submitButtonClicked', false);
      },
      onSecondary: function () {
        this._super();
        App.router.set('nextBtnClickInProgress', false);
        self.set('submitButtonClicked', false);
      },
      onClose: function () {
        this._super();
        self.set('submitButtonClicked', false);
      }
    });
  },

  getHosts: function () {
    return Em.keys(this.get('content.hosts'));
  }
});
