import { computed, get, set } from '@ember/object';
import { inject as service } from '@ember/service';
import Resource from '@rancher/ember-api-store/models/resource';
import { parseExternalId } from 'ui/utils/parse-externalid';
import { convertToMillis } from 'shared/utils/util';
import { parseSi } from 'shared/utils/parse-unit';
import C from 'ui/utils/constants';
import { hasMany, reference } from '@rancher/ember-api-store/utils/denormalize';
import StateCounts from 'ui/mixins/state-counts';
const ISTIO_INJECTION = 'istio-injection'
const ENABLED = 'enabled';

export function convertResourceQuota(key, value) {
  let out;

  switch (key) {
  case 'limitsCpu':
  case 'requestsCpu':
    out = convertToMillis(value);
    break;
  case 'limitsMemory':
  case 'requestsMemory':
    out = parseSi(value, 1024) / 1048576;
    break;
  case 'requestsStorage':
    out = parseSi(value) / (1024 ** 3);
    break;
  default:
    out = parseInt(value, 10);
  }

  return out;
}

export function activeIcon(ns) {
  if ( ns.get('system') ) {
    return 'icon icon-gear';
  } else {
    return 'icon icon-layers';
  }
}

export function tagsToArray(str, normalize = true) {
  return (str || '').split(/\s*,\s*/)
    .map((tag) => {
      if (normalize) {
        return normalizeTag(tag);
      } else {
        return tag;
      }
    })
    .filter((tag) => tag.length > 0);
}

export function normalizeTag(name) {
  return (name || '').trim().toLowerCase();
}

export function normalizeTags(ary) {
  return (ary || []).map(normalizeTag).filter((str) => str.length > 0);
}

var Namespace = Resource.extend(StateCounts, {
  k8s:          service(),
  intl:         service(),
  modalService: service('modal'),
  catalog:      service(),
  scope:        service(),
  router:       service(),
  projectStore: service('store'),
  globalStore:  service(),
  clusterStore: service(),
  growl:        service(),

  pods:                  hasMany('id', 'pod', 'namespaceId', 'projectStore', null, 'clusterStore'),
  configMaps:            hasMany('id', 'configMap', 'namespaceId', 'projectStore', null, 'clusterStore'),
  workloads:             hasMany('id', 'workload', 'namespaceId', 'projectStore', null, 'clusterStore'),
  services:              hasMany('id', 'service', 'namespaceId', 'projectStore', null, 'clusterStore'),
  secrets:               hasMany('id', 'namespacedSecret', 'namespaceId', 'projectStore', null, 'clusterStore'),
  ingress:               hasMany('id', 'ingress', 'namespaceId', 'projectStore', null, 'clusterStore'),
  volumes:               hasMany('id', 'persistentVolumeClaim', 'namespaceId', 'projectStore', null, 'clusterStore'),
  type:                  'namespace',
  project:               reference('projectId', 'project', 'globalStore'),

  init() {
    this._super(...arguments);
    // @TODO-2.0 this.defineStateCounts('services', 'serviceStates', 'serviceCountSort');
  },

  availableActions: computed('projectId', 'actionLinks.@each.{move}', 'scope.currentCluster.istioEnabled', 'scope.currentCluster.systemProject', 'autoInjectionEnabled', function() {
    let aa = get(this, 'actionLinks') || {};

    let out = [
      {
        label:    'action.move',
        icon:     'icon icon-fork',
        action:   'move',
        enabled:  !!aa.move,
        bulkable: true
      },
      {
        label:    'action.enableAutoInject',
        icon:     'icon icon-plus-circle',
        action:   'enableAutoInject',
        enabled:  get(this, 'scope.currentCluster.istioEnabled') && !!get(this, 'scope.currentCluster.systemProject') && !get(this, 'autoInjectionEnabled'),
        bulkable: true
      },
      {
        label:    'action.disableAutoInject',
        icon:     'icon icon-minus-circle',
        action:   'disableAutoInject',
        enabled:  get(this, 'scope.currentCluster.istioEnabled') && !!get(this, 'scope.currentCluster.systemProject') && get(this, 'autoInjectionEnabled'),
        bulkable: true
      },
      { divider: true },
    ];

    return out;
  }),

  combinedState: computed('state', 'healthState', function() {
    var stack = this.get('state');
    var health = this.get('healthState');

    if ( stack === 'active' && health ) {
      return health;
    } else {
      return stack;
    }
  }),

  externalIdInfo: computed('externalId', function() {
    return parseExternalId(this.get('externalId'));
  }),

  isDefault: computed('name', function() {
    return (this.get('name') || '').toLowerCase() === 'default';
  }),

  isEmpty: computed('pods.length', 'workloads.length', function() {
    return (get(this, 'pods.length') || 0 + get(this, 'workloads.length') || 0) === 0;
  }),

  hasProject: computed('project', function() {
    return !!get(this, 'project');
  }),

  isFromCatalog: computed('externalIdInfo.kind', function() {
    let kind = this.get('externalIdInfo.kind');

    return kind === C.EXTERNAL_ID.KIND_CATALOG || kind === C.EXTERNAL_ID.KIND_SYSTEM_CATALOG;
  }),

  // This only works if the templates have already been loaded elsewhere...
  catalogTemplate: computed('externalIdInfo.templateId', function() {
    return this.get('catalog').getTemplateFromCache(this.get('externalIdInfo.templateId'));
  }),

  icon: computed('catalogTemplate', function() {
    let tpl = this.get('catalogTemplate');

    if ( tpl ) {
      return tpl.linkFor('icon');
    }
  }),

  grouping: computed('externalIdInfo.kind', 'group', 'system', function() {
    var kind = this.get('externalIdInfo.kind');

    if ( kind === C.EXTERNAL_ID.KIND_KUBERNETES || kind === C.EXTERNAL_ID.KIND_LEGACY_KUBERNETES ) {
      return C.EXTERNAL_ID.KIND_KUBERNETES;
    } else if ( this.get('system') ) {
      return C.EXTERNAL_ID.KIND_INFRA;
    } else {
      return C.EXTERNAL_ID.KIND_USER;
    }
  }),

  normalizedTags: computed('tags.[]', function() {
    return normalizeTags(this.get('tags'));
  }),

  autoInjectionEnabled: computed('labels', function() {
    const labels = get(this, 'labels')

    return labels && labels[ISTIO_INJECTION] === ENABLED;
  }),

  validateResourceQuota(originLimit) {
    const intl = get(this, 'intl');
    let errors = [];

    const resourceQuota = get(this, 'resourceQuota.limit') || {};
    const total = get(this, 'project.resourceQuota.limit');
    const used = get(this, 'project.resourceQuota.usedLimit') || {};

    if ( total ) {
      Object.keys(resourceQuota).forEach((key) => {
        if ( !resourceQuota[key] && parseInt(resourceQuota[key], 10) !== 0 ) {
          errors.push(intl.t('formResourceQuota.errors.limitRequired', { resource: intl.t(`formResourceQuota.resources.${ key }`) }));
        }

        if ( resourceQuota[key] ) {
          const t = convertResourceQuota(key, total[key]);
          const u = convertResourceQuota(key, used[key] || 0);
          const v = convertResourceQuota(key, resourceQuota[key]);
          const originValue = originLimit && originLimit[key] ? originLimit[key] : 0;
          const o = convertResourceQuota(key, originValue);

          const left = t - u + o;

          if ( v > left ) {
            errors.push(intl.t('formResourceQuota.errors.invalidLimit', {
              resource: intl.t(`formResourceQuota.resources.${ key }`),
              left,
              total:    t,
              used:     u - o,
            }));
          }
        }
      });
    }

    return errors;
  },

  actions: {
    edit() {
      this.get('modalService').toggleModal('modal-edit-namespace', this);
    },

    delete() {
      return this._super().then(() => {
        if ( this.get('application.currentRouteName') === 'stack.index' ) {
          this.get('router').transitionTo('containers');
        }
      });
    },

    move() {
      this.get('modalService').toggleModal('modal-move-namespace', this);
    },

    enableAutoInject() {
      this.autoInjectToggle()
    },

    disableAutoInject() {
      this.autoInjectToggle()
    },
  },

  hasTags(want) {
    if ( !want || !want.length ) {
      return true;
    }

    want = normalizeTags(want);

    let have = this.get('normalizedTags');

    for ( let i = 0 ; i < want.length ; i++ ) {
      if ( !have.includes(want[i]) ) {
        return false;
      }
    }

    return true;
  },

  autoInjectToggle() {
    const labels = get(this, 'labels')
    const clone = this.clone()

    if (get(this, 'autoInjectionEnabled')) {
      delete labels['istio-injection']
    } else {
      labels[ISTIO_INJECTION] = ENABLED;
    }
    set(clone, 'labels', labels)
    clone.save().catch((err) => get(this, 'growl').fromError('Error:', err))
  },
});

Namespace.reopenClass({
  stateMap: {
    'active':             {
      icon:  activeIcon,
      color: 'text-success'
    },
    'rolling-back':       {
      icon:  'icon icon-history',
      color: 'text-info'
    },
    'upgraded':           {
      icon:  'icon icon-arrow-circle-up',
      color: 'text-info'
    },
    'upgrading':          {
      icon:  'icon icon-arrow-circle-up',
      color: 'text-info'
    },
  }
});

export default Namespace;
