angular.module('portainer.docker').controller('SwarmNodeDetailsPanelController', [
  'NodeService',
  'LabelHelper',
  'Notifications',
  '$state',
  function SwarmNodeDetailsPanelController(NodeService, LabelHelper, Notifications, $state) {
    var ctrl = this;
    ctrl.state = {
      managerAddress: '',
      hasChanges: false,
    };
    ctrl.$onChanges = $onChanges;
    ctrl.addLabel = addLabel;
    ctrl.updateNodeLabels = updateNodeLabels;
    ctrl.updateNodeAvailability = updateNodeAvailability;
    ctrl.saveChanges = saveChanges;
    ctrl.cancelChanges = cancelChanges;

    var managerRole = 'manager';

    function $onChanges() {
      if (!ctrl.details) {
        return;
      }
      if (ctrl.details.role === managerRole) {
        ctrl.state.managerAddress = '(' + ctrl.details.managerAddress + ')';
      }
    }

    function addLabel() {
      ctrl.details.nodeLabels.push({
        key: '',
        value: '',
        originalValue: '',
        originalKey: '',
      });
    }

    function updateNodeLabels(labels) {
      ctrl.details.nodeLabels = labels;
      ctrl.state.hasChanges = true;
    }

    function updateNodeAvailability(availability) {
      ctrl.details.availability = availability;
      ctrl.state.hasChanges = true;
    }

    function saveChanges() {
      var originalNode = ctrl.originalNode;
      var config = {
        Name: originalNode.Name,
        Availability: ctrl.details.availability,
        Role: originalNode.Role,
        Labels: LabelHelper.fromKeyValueToLabelHash(ctrl.details.nodeLabels),
        Id: originalNode.Id,
        Version: originalNode.Version,
      };

      NodeService.updateNode(config).then(onUpdateSuccess).catch(notifyOnError);

      function onUpdateSuccess() {
        Notifications.success('Node successfully updated', 'Node updated');
        $state.go('docker.nodes.node', { id: originalNode.Id }, { reload: true });
      }

      function notifyOnError(error) {
        Notifications.error('Failure', error, 'Failed to update node');
      }
    }

    function cancelChanges() {
      cancelLabelChanges();
      ctrl.details.availability = ctrl.originalNode.Availability;
      ctrl.state.hasChanges = false;
    }

    function cancelLabelChanges() {
      ctrl.details.nodeLabels = ctrl.details.nodeLabels
        .filter(function (label) {
          return label.originalValue || label.originalKey;
        })
        .map(function (label) {
          return Object.assign(label, {
            value: label.originalValue,
            key: label.originalKey,
          });
        });
    }
  },
]);
