import { inject as service } from '@ember/service';
import Component from '@ember/component';
import { computed } from '@ember/object';
import { isPresent } from '@ember/utils';
import { Promise } from 'rsvp';
import { validator, buildValidations } from 'ember-cp-validations';
import ValidationErrorDisplay from 'ilios-common/mixins/validation-error-display';

const Validations = buildValidations({
  newTermTitle: [
    validator('presence', true),
    validator('length', {
      min: 1,
      max: 200
    }),
    validator('async-exclusion', {
      dependentKeys: ['model.vocabulary.terms.@each.title'],
      in: computed('model.vocabulary.terms.@each.title', function(){
        return new Promise(resolve => {
          const vocabulary = this.get('model.vocabulary');
          if (isPresent(vocabulary)) {
            return vocabulary.get('terms').then(terms => {
              resolve(terms.filterBy('isTopLevel', true).mapBy('title'));
            });
          }
          resolve([]);
        });

      }),
      descriptionKey: 'general.term',
    })
  ],
});

export default Component.extend(Validations, ValidationErrorDisplay, {
  store: service(),
  vocabulary: null,
  canUpdate: false,
  canCreate: false,
  title: null,
  isActive: null,
  newTermTitle: null,
  isSavingNewTerm: false,
  newTerm: null,
  classNames: ['school-vocabulary-manager'],
  'data-test-school-vocabulary-manager': true,
  sortedTerms: computed('vocabulary.terms.[]', 'newTerm', function(){
    return new Promise(resolve => {
      const vocabulary = this.vocabulary;
      if (isPresent(vocabulary)) {
        vocabulary.get('terms').then(terms => {
          resolve(
            terms.filterBy('isTopLevel')
              .filterBy('isNew', false)
              .filterBy('isDeleted', false)
              .sortBy('title')
          );
        });
      }
    });
  }),
  didReceiveAttrs(){
    this._super(...arguments);
    const vocabulary = this.vocabulary;
    if (vocabulary) {
      this.set('title', vocabulary.get('title'));
      this.set('isActive', vocabulary.get('active'));
    }
  },
  actions: {
    changeVocabularyTitle(){
      const vocabulary = this.vocabulary;
      const title = this.title;
      vocabulary.set('title', title);
      return vocabulary.save();
    },
    revertVocabularyTitleChanges(){
      const vocabulary = this.vocabulary;
      this.set('title', vocabulary.get('title'));
    },
    createTerm(){
      this.send('addErrorDisplayFor', 'newTermTitle');
      this.set('isSavingNewTerm', true);
      this.validate().then(({validations}) => {
        if (validations.get('isValid')) {
          this.send('removeErrorDisplayFor', 'newTermTitle');
          let title = this.newTermTitle;
          const vocabulary = this.vocabulary;
          const store = this.store;
          let term = store.createRecord('term', {title, vocabulary, active: true});
          return term.save().then((newTerm) => {
            this.set('newTermTitle', null);
            this.set('newTerm', newTerm);
          });
        }
      }).finally(() => {
        this.set('isSavingNewTerm', false);
      });
    }
  },
  keyUp(event) {
    const keyCode = event.keyCode;
    const target = event.target;

    if ('text' !== target.type) {
      return;
    }

    if (13 === keyCode) {
      this.send('createTerm');
    }
  },
});

@@ -175,40 +175,8 @@
 s';%0A
-import %7B Promise %7D from 'rsvp';%0A
 impo
@@ -235,24 +235,24 @@
 lidations';%0A
+
 import Valid
@@ -628,16 +628,22 @@
 .title',
+ async
  functio
@@ -651,50 +651,8 @@
 ()%7B%0A
-        return new Promise(resolve =%3E %7B%0A  
     
@@ -708,26 +708,24 @@
 ');%0A        
-  
 if (isPresen
@@ -755,60 +755,46 @@
     
-  return vocabulary.get('terms').then(terms =%3E %7B%0A   
+const terms = await vocabulary.terms;%0A
     
@@ -799,25 +799,23 @@
         
- 
 re
-solve(
+turn 
 terms.fi
@@ -847,33 +847,32 @@
 ).mapBy('title')
-)
 ;%0A            %7D)
@@ -861,31 +861,25 @@
 ');%0A        
-    %7D);
+%7D
 %0A          %7D
@@ -879,45 +879,17 @@
     
-  %7D%0A          resolve(%5B%5D);%0A        %7D)
+return %5B%5D
 ;%0A%0A 
@@ -1350,16 +1350,22 @@
 ewTerm',
+ async
  functio
@@ -1373,46 +1373,8 @@
 ()%7B%0A
-    return new Promise(resolve =%3E %7B%0A  
     
@@ -1409,26 +1409,24 @@
 bulary;%0A    
-  
 if (isPresen
@@ -1452,80 +1452,58 @@
     
-  vocabulary.get('terms').then(terms =%3E %7B%0A          resolve(%0A           
+const terms = await vocabulary.terms;%0A      return
  ter
@@ -1528,38 +1528,32 @@
 Level')%0A        
- 
-     
 .filterBy('isNew
@@ -1570,22 +1570,16 @@
         
-     
- 
 .filterB
@@ -1608,22 +1608,16 @@
         
-      
 .sortBy(
@@ -1628,49 +1628,15 @@
 le')
-%0A          );%0A        %7D);%0A      %7D%0A    %7D);
+;%0A    %7D
 %0A  %7D
@@ -2199,16 +2199,22 @@
  %7D,%0A    
+async 
 createTe
@@ -2326,48 +2326,67 @@
    t
-his.validate().then((%7Bvalidations%7D) =%3E %7B
+ry %7B%0A        const %7B validations %7D = await this.validate();
 %0A   
@@ -2863,23 +2863,16 @@
    %7D
-).
+ 
 finally
-(() =%3E
  %7B%0A 
@@ -2914,25 +2914,23 @@
 false);%0A
+
       %7D
-);
 %0A    %7D%0A 

Update component