import AWS = require('aws-sdk');
import { Cacher } from './base';
import { NamespaceCache } from '../../interfaces/tagcache';
import { SensuTagSet } from '../../interfaces/sensu';

export class ALBTags extends Cacher {

  elbv2: AWS.ELBv2;

  constructor() {
    super();
    this.elbv2 = new AWS.ELBv2();
  }

  public get(dimensions: AWS.CloudWatch.Types.Dimensions, cache: NamespaceCache): SensuTagSet {
    let d = this.mergeDimensions(dimensions);

    let lbTags = [];
    let tgTags = [];

    if (d.LoadBalancer) {
      const lbArn = this.arn_builder('elasticloadbalancing', 'loadbalancer/' + d.LoadBalancer);
      lbTags = [].concat.apply([], cache.Dimension.LoadBalancers.filter(t => {
        return (t.ResourceArn === lbArn);
      }).map(t => { return t.Tags }))
    }

    if (d.TargetGroup) {
      const tgArn = this.arn_builder('elasticloadbalancing', d.TargetGroup);
      tgTags = [].concat.apply([], cache.Dimension.TargetGroups.filter(t => {
        return (t.ResourceArn === tgArn);
      }).map(t => { return t.Tags }))
    }

    return this.mergeTags([].concat(lbTags, tgTags))

  }

  public async fill() {
    let loadBalancers = this.elbv2.describeLoadBalancers().promise()
    let targetGroups = this.elbv2.describeTargetGroups().promise()

    return Promise.all([loadBalancers, targetGroups]).then(async resp => {
      let loadBalancerArns = resp[0].LoadBalancers.map(lb => { return lb.LoadBalancerArn })
      let targetGroupArns = resp[1].TargetGroups.map(tb => { return tb.TargetGroupArn })

      const batchSize = 20;
      const lbBatches = Math.ceil(loadBalancerArns.length / batchSize);
      const tgBatches = Math.ceil(targetGroupArns.length / batchSize);

      let lbPromises = [];
      let tgPromises = [];

      for (let i = 0; i < lbBatches; i++) {
        let resourceArnsSlice = loadBalancerArns.slice(i * batchSize, (i * batchSize) + batchSize)
        lbPromises.push(this.elbv2.describeTags({ ResourceArns: resourceArnsSlice }).promise());
      }

      for (let i = 0; i < tgBatches; i++) {
        let resourceArnsSlice = targetGroupArns.slice(i * batchSize, (i * batchSize) + batchSize)
        tgPromises.push(this.elbv2.describeTags({ ResourceArns: resourceArnsSlice }).promise());
      }

      let lbCache = Promise.all(lbPromises).then(d => {
        return [].concat.apply([], d.map(a => { return a.TagDescriptions }))
      });

      let tgCache = Promise.all(tgPromises).then(d => {
        return [].concat.apply([], d.map(a => { return a.TagDescriptions }))
      });

      return Promise.all([lbCache, tgCache]).then(d => {
        let cache: NamespaceCache = {
          LastUpdated: new Date(),
          Dimension: {
            LoadBalancers: d[0],
            TargetGroups: d[1]
          }
        }
        return cache;
      });

    });
  }
}
