text: 'use strict';
  
  import { map } from 'lodash';
  
  import { AccountService, InfrastructureCaches, ModalWizard } from '@spinnaker/core';
  
  import { AWSProviderSettings } from 'amazon/aws.settings';
  import { VpcReader } from 'amazon/vpc';
  
  describe('Controller: CreateSecurityGroup', function () {
    beforeEach(
      window.module(require('./CreateSecurityGroupCtrl').name, require('./configSecurityGroup.mixin.controller').name),
    );
  
    afterEach(AWSProviderSettings.resetToOriginal);
  
    describe('filtering', function () {
      this.oldGet = InfrastructureCaches.get;
  
      beforeEach(() => {
        InfrastructureCaches.get = () => {
          return {
            getStats: () => {
              return { ageMax: 0 };
            },
          };
        };
      });
      afterEach(() => {
        InfrastructureCaches.get = this.oldGet;
      });
  
      // Initialize the controller and a mock scope
      beforeEach(
        window.inject(function ($controller, $rootScope, $q, securityGroupReader) {
          this.$scope = $rootScope.$new();
          this.$q = $q;
          this.securityGroupReader = securityGroupReader;
  
          spyOn(AccountService, 'listAllAccounts').and.returnValue($q.when([{ name: 'prod' }, { name: 'test' }]));
  
          spyOn(AccountService, 'getRegionsForAccount').and.returnValue($q.when(['us-east-1', 'us-west-1']));
  
          spyOn(VpcReader, 'listVpcs').and.returnValue(
            $q.when([
              { id: 'vpc1-pe', name: 'vpc 1', account: 'prod', region: 'us-east-1', deprecated: false, label: 'vpc 1' },
              { id: 'vpc2-pw', name: 'vpc 2', account: 'prod', region: 'us-west-1', deprecated: false, label: 'vpc 2' },
              { id: 'vpc1-te', name: 'vpc 1', account: 'test', region: 'us-east-1', deprecated: false, label: 'vpc 1' },
              { id: 'vpc2-te', name: 'vpc 2', account: 'test', region: 'us-east-1', deprecated: false, label: 'vpc 2' },
              { id: 'vpc2-tw', name: 'vpc 2', account: 'test', region: 'us-west-1', deprecated: false, label: 'vpc 2' },
            ]),
          );
  
          spyOn(this.securityGroupReader, 'getAllSecurityGroups').and.returnValue(
            $q.when({
              prod: {
                aws: {
                  'us-east-1': [
                    { name: 'group1', vpcId: null, id: '1' },
                    { name: 'group2', vpcId: null, id: '2' },
                    { name: 'group3', vpcId: 'vpc1-pe', id: '3' },
                  ],
                  'us-west-1': [
                    { name: 'group1', vpcId: null, id: '1' },
                    { name: 'group3', vpcId: 'vpc2-pw', id: '3' },
                  ],
                },
              },
              test: {
                aws: {
                  'us-east-1': [
                    { name: 'group1', vpcId: null, id: '1' },
                    { name: 'group2', vpcId: 'vpc1-te', id: '2' },
                    { name: 'group3', vpcId: 'vpc1-te', id: '3' },
                    { name: 'group4', vpcId: 'vpc2-te', id: '4' },
                  ],
                  'us-west-1': [
                    { name: 'group1', vpcId: null, id: '1' },
                    { name: 'group3', vpcId: 'vpc1-tw', id: '3' },
                    { name: 'group3', vpcId: 'vpc2-tw', id: '3' },
                    { name: 'group5', vpcId: 'vpc2-tw', id: '5' },
                  ],
                },
              },
            }),
          );
  
          this.initializeCtrl = function () {
            this.ctrl = $controller('awsCreateSecurityGroupCtrl', {
              $scope: this.$scope,
              $uibModalInstance: { result: this.$q.when(null) },
              securityGroupReader: this.securityGroupReader,
              application: this.application || { attributes: {} },
              securityGroup: { regions: [], securityGroupIngress: [] },
            });
            this.$scope.$digest();
          };
        }),
      );
  
      it('initializes with no firewalls available for ingress permissions', function () {
        this.initializeCtrl();
        expect(this.$scope.availableSecurityGroups.length).toBe(0);
      });
  
      it('sets up available firewalls once an account and region are selected', function () {
        this.initializeCtrl();
        this.$scope.securityGroup.credentials = 'prod';
        this.ctrl.accountUpdated();
        this.$scope.$digest();
        expect(this.$scope.availableSecurityGroups.length).toBe(0);
  
        this.$scope.securityGroup.regions = ['us-east-1'];
        this.ctrl.accountUpdated();
        this.$scope.$digest();
        expect(this.$scope.availableSecurityGroups.length).toBe(1);
        expect(this.$scope.existingSecurityGroupNames).toEqual(['group3']);
      });
  
      it('filters existing names based on join of groups from all regions', function () {
        this.initializeCtrl();
        this.$scope.securityGroup.credentials = 'test';
        this.$scope.securityGroup.regions = ['us-east-1', 'us-west-1'];
        this.$scope.securityGroup.vpcId = 'vpc2-te';
        this.$scope.securityGroup.vpcName = 'vpc 2';
        this.ctrl.accountUpdated();
        this.$scope.$digest();
        expect(this.$scope.availableSecurityGroups.length).toBe(0);
        expect(this.$scope.existingSecurityGroupNames.sort()).toEqual(['group3', 'group4', 'group5']);
      });
  
      it('filters available names based on intersection of groups from all regions', function () {
        this.initializeCtrl();
        this.$scope.securityGroup.credentials = 'test';
        this.$scope.securityGroup.regions = ['us-east-1', 'us-west-1'];
        this.$scope.securityGroup.vpcId = 'vpc1-tw';
        this.ctrl.accountUpdated();
        this.$scope.$digest();
        expect(this.$scope.availableSecurityGroups.length).toBe(0);
      });
  
      it('filters VPCs based on account + region', function () {
        this.initializeCtrl();
        this.$scope.securityGroup.credentials = 'test';
        this.$scope.securityGroup.regions = ['us-east-1', 'us-west-1'];
        this.ctrl.accountUpdated();
        this.$scope.$digest();
        expect(map(this.$scope.vpcs, 'label').sort()).toEqual(['vpc 2']);
  
        this.$scope.securityGroup.regions = ['us-east-1'];
        this.ctrl.accountUpdated();
        this.$scope.$digest();
        expect(map(this.$scope.vpcs, 'label').sort()).toEqual(['vpc 1', 'vpc 2']);
      });
  
      it('loves a default VPC!', function () {
        AWSProviderSettings.defaults.vpc = 'vpc 2';
        AWSProviderSettings.classicLaunchLockout = -1;
        this.initializeCtrl();
        this.$scope.securityGroup.credentials = 'test';
        this.$scope.securityGroup.regions = ['us-east-1'];
        this.$scope.securityGroup.vpcName = 'vpc 2';
        this.ctrl.regionUpdated();
        this.$scope.$digest();
        expect(this.$scope.securityGroup.vpcId).toBe('vpc2-te');
      });
  
      describe('firewall removal', function () {
        beforeEach(function () {
          spyOn(ModalWizard, 'markDirty').and.returnValue(null);
          this.initializeCtrl();
          let securityGroup = this.$scope.securityGroup;
          securityGroup.credentials = 'prod';
          securityGroup.regions = ['us-east-1'];
          this.ctrl.accountUpdated();
          this.$scope.$digest();
        });
  
        it('removes rules that are not available when account changes', function () {
          let securityGroup = this.$scope.securityGroup;
          securityGroup.credentials = 'test';
          this.ctrl.accountUpdated();
          this.$scope.$digest();
          this.$scope.availableSecurityGroups.forEach((group) =>
            securityGroup.securityGroupIngress.push({ name: group }),
          );
          expect(securityGroup.securityGroupIngress.length).toBe(2);
  
          securityGroup.credentials = 'prod';
          this.ctrl.accountUpdated();
          this.$scope.$digest();
          expect(this.$scope.state.removedRules.length).toBe(1);
          expect(ModalWizard.markDirty).toHaveBeenCalledWith('Ingress');
        });
  
        it('does not repeatedly add removed rule warnings when multiple rules for the same group are removed', function () {
          let securityGroup = this.$scope.securityGroup;
          securityGroup.credentials = 'test';
          this.ctrl.accountUpdated();
          this.$scope.$digest();
          this.$scope.availableSecurityGroups.forEach((group) => {
            securityGroup.securityGroupIngress.push({ name: group, startPort: 7001, endPort: 7001, protocol: 'HTTPS' });
            securityGroup.securityGroupIngress.push({ name: group, startPort: 7000, endPort: 7000, protocol: 'HTTP' });
          });
          expect(securityGroup.securityGroupIngress.length).toBe(4);
  
          securityGroup.credentials = 'prod';
          this.ctrl.accountUpdated();
          this.$scope.$digest();
          expect(this.$scope.state.removedRules).toEqual(['group2']);
          expect(ModalWizard.markDirty).toHaveBeenCalledWith('Ingress');
        });
      });
  
      describe('classic locking', function () {
        function init(self) {
          self.initializeCtrl();
          self.ctrl.regionUpdated();
          self.$scope.$digest();
        }
  
        it('does not hide classic when aws provider not configured', function () {
          init(this);
          expect(this.$scope.hideClassic).toBe(false);
        });
  
        it('does not hide classic when classicLaunchLockout not configured', function () {
          AWSProviderSettings.classicLaunchLockout = undefined;
          init(this);
          expect(this.$scope.hideClassic).toBe(false);
        });
  
        it('does not hide classic when application has no attributes', function () {
          AWSProviderSettings.classicLaunchLockout = 10;
          init(this);
          expect(this.$scope.hideClassic).toBe(false);
  
          this.application = {};
          init(this);
          expect(this.$scope.hideClassic).toBe(false);
        });
  
        it('does not hide classic when application is older than lockout date', function () {
          this.application = { attributes: { createTs: 9 } };
          init(this);
          expect(this.$scope.hideClassic).toBe(false);
        });
  
        it('hides classic when application createTs is numeric and the same as lockout', function () {
          AWSProviderSettings.classicLaunchLockout = 10;
          this.application = { attributes: { createTs: 10 } };
          init(this);
          expect(this.$scope.hideClassic).toBe(true);
        });
  
        it('hides classic when application createTs is numeric and after lockout', function () {
          AWSProviderSettings.classicLaunchLockout = 10;
          this.application = { attributes: { createTs: 11 } };
          init(this);
          expect(this.$scope.hideClassic).toBe(true);
        });
  
        it('hides classic when application createTs is a string and the same as lockout', function () {
          AWSProviderSettings.classicLaunchLockout = 10;
          this.application = { attributes: { createTs: '10' } };
          init(this);
          expect(this.$scope.hideClassic).toBe(true);
        });
  
        it('hides classic when application createTs is a string and after lockout', function () {
          AWSProviderSettings.classicLaunchLockout = 10;
          this.application = { attributes: { createTs: '11' } };
          init(this);
          expect(this.$scope.hideClassic).toBe(true);
        });
  
        it('sets vpcId to first active if classic is locked', function () {
          AWSProviderSettings.classicLaunchLockout = 10;
          this.application = { attributes: { createTs: 10 } };
          this.initializeCtrl();
  
          this.$scope.securityGroup.credentials = 'prod';
          this.$scope.securityGroup.regions = ['us-east-1'];
          this.$scope.securityGroup.vpcName = 'vpc 1';
  
          this.ctrl.regionUpdated();
          this.$scope.$digest();
  
          expect(this.$scope.securityGroup.vpcId).toBe('vpc1-pe');
        });
  
        it('leaves vpcId alone if already selected and classic locked', function () {
          AWSProviderSettings.classicLaunchLockout = 10;
  
          this.application = { attributes: { createTs: 10 } };
          this.initializeCtrl();
          this.$scope.securityGroup.vpcId = 'vpc2-te';
          this.$scope.securityGroup.vpcName = 'vpc 2';
          this.$scope.securityGroup.credentials = 'test';
          this.$scope.securityGroup.regions = ['us-east-1'];
          this.ctrl.regionUpdated();
          this.$scope.$digest();
          expect(this.$scope.securityGroup.vpcId).toBe('vpc2-te');
        });
      });
    });
  });
  