import { once } from '@ember/runloop';
import { get, set, computed, observer, setProperties } from '@ember/object';
import Mixin from '@ember/object/mixin';
import C from 'ui/utils/constants';
import { inject as service } from "@ember/service";
import Semver from 'npm:semver';

const NONE       = 'none',
      LOADING    = 'loading',
      CURRENT    = 'current',
      AVAILABLE  = 'available',
      REQUIRED   = 'required',
      INPROGRESS = 'inprogress',
      UPGRADED   = 'upgraded',
      NOTFOUND   = 'notfound',
      ERROR      = 'error';

const INPROGRESS_STATES = [
  'upgrading',
  'canceled-upgrade',
  'canceling-rollback',
  'canceling-upgrade',
  'finishing-upgrade',
  'rolling-back',
];

export default Mixin.create({
  model               : null,
  upgradeOnly         : true,

  intl                : service(),
  catalog             : service(),
  router: service(),

  upgradeInfo         : null,
  upgradeStatus       : null,
  latestVersion       : null,

  init() {
    this._super(...arguments);
    this.updateStatus();
  },

  color: computed('upgradeStatus', function() {
    switch ( get(this, 'upgradeStatus') ) {
      case NONE:
        return 'none';
      case CURRENT:
      case LOADING:
        return 'bg-default';
      case NOTFOUND:
      case ERROR:
      case INPROGRESS:
        return 'bg-disabled';
      case REQUIRED:
        return 'bg-error';
      case AVAILABLE:
      case UPGRADED:
        return 'bg-warning';
    }
  }),

  currentVersion: computed('model.externalIdInfo.{version}','model.externalId', function() {
    let text = get(this, 'intl').findTranslationByKey('upgradeBtn.version.current');
    let version = get(this, 'model.externalIdInfo.version');
    if (typeof version === 'string' || typeof version === 'number') {
      return `${text}: ${get(this, 'upgradeInfo.version')}`;
    } else {
      return null;
    }
  }),

  externalIdChanged: observer('model.{externalId,state}', function() {
    once(() => {
      this.updateStatus();
    });
  }),

  doUpgrade() {
    let status = get(this, 'upgradeStatus');

    if ( [REQUIRED,AVAILABLE,CURRENT].indexOf(status) >= 0 ) {
      let templateId = get(this, 'model.externalIdInfo.templateId');
      let versionId  = get(this, 'latestVersion');
      let catalogId  = get(this, 'model.externalIdInfo.catalog');

      get(this, 'router').transitionTo('catalog-tab.launch', templateId, {queryParams: {
        upgrade: versionId,
        catalog: catalogId,
        namespaceId: get(this, 'model.targetNamespace'),
        appId: get(this, 'model.id'),
      }});

    } else if ( status === UPGRADED ) {

      get(this, 'model').send('finishUpgrade');
    }
  },

  updateStatus() {
    let state           = get(this, 'model.state');
    let info            = get(this, 'model.externalIdInfo');
    let catalogTemplate = get(this, 'model.catalogTemplate');
    let upgradeVersions = {};
    let allVersions     = {};

    if ( state === 'upgraded' ) {
      set(this, 'upgradeStatus', UPGRADED);
      return;
    }

    if ( INPROGRESS_STATES.indexOf(state) >= 0 ) {
      set(this, 'upgradeStatus', INPROGRESS);
      return;
    }

    if ( info && C.EXTERNAL_ID.UPGRADEABLE.indexOf(info.kind) >= 0 ) {
      set(this, 'upgradeStatus', LOADING);
    } else {
      set(this, 'upgradeStatus', NONE);
    }

    if ( catalogTemplate ) {
      upgradeVersions = parseUpgradeVersions(
        get(catalogTemplate, 'versionLinks'),
        get(info, 'version'),
        get(this, 'model')
      );
      get(catalogTemplate, 'versionLinks');
    }

    if (Object.keys(upgradeVersions).length >= 1) {
      setProperties(this, {
        upgradeStatus: AVAILABLE,
        latestVersion: Object.keys(upgradeVersions)[Object.keys(upgradeVersions).length-1],
      });
    } else {
      setProperties(this, {
        upgradeStatus: CURRENT,
        latestVersion: get(info, 'version'),
      });
    }

    // console.log('upgradeVersions', upgradeVersions);

    function parseUpgradeVersions(allVersions, currentVersion) {
      let keys = Object.keys(allVersions);
      let upgrades = {};

      keys.forEach( k => {
        let gt = Semver.gt(k, currentVersion);
        if (gt) {
          upgrades[k] = allVersions[k];
        }
        // console.log(k, currentVersion, gt);
      });


      return upgrades;
    }

    setProperties(this, {
      allVersions: allVersions,
      upgradeVersions: upgradeVersions
    });
    return;
  },

});

@@ -872,16 +872,65 @@
   router
+              : service(),%0A  growl               
 : servic
@@ -3544,27 +3544,64 @@
     get(
-this, 'mode
+catalogTemplate, 'name'),%0A        get(this,'grow
 l')%0A    
@@ -4125,16 +4125,37 @@
 tVersion
+, templateName, growl
 ) %7B%0A    
@@ -4214,24 +4214,30 @@
 rades = %7B%7D;%0A
+      
 %0A      keys.
@@ -4248,24 +4248,40 @@
 ach( k =%3E %7B%0A
+        try %7B%0A  
         let 
@@ -4319,24 +4319,26 @@
 n);%0A        
+  
 if (gt) %7B%0A  
@@ -4331,24 +4331,26 @@
   if (gt) %7B%0A
+  
           up
@@ -4381,24 +4381,26 @@
 k%5D;%0A        
+  
 %7D%0A        //
@@ -4401,46 +4401,115 @@
     
-// console.log(k, currentVersion, gt);
+%7D catch (err) %7B%0A          growl.fromError(%60Invalid catalog app version in $%7BtemplateName%7D%60, err);%0A        %7D
 %0A   
@@ -4516,17 +4516,16 @@
    %7D);%0A%0A
-%0A
       re

Fix catalog issue