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

export class EC2Tags extends Cacher {

  ec2: AWS.EC2;
  asg: AWS.AutoScaling;

  constructor() {
    super()
    this.ec2 = new AWS.EC2();
    this.asg = new AWS.AutoScaling();
  }

  public get(dimensions: AWS.CloudWatch.Types.Dimensions, cache: NamespaceCache): SensuTagSet {
    let d = this.mergeDimensions(dimensions);
    // Filter out stats we don't care about (by AMI, by Instance Type, by null?)
    // Returning {} on a taggable namespace drops the metric via the filter in processor.ts
    // I'm assuming keeping the by AutoScalingGroup metrics will be interesting...
    if (!d.InstanceId && !d.AutoScalingGroupName) {
      return {};
    }

    let ec2Tags = [];
    let asgTags = [];

    if (d.AutoScalingGroupName) {
      asgTags = [].concat.apply([], cache.Dimension.AutoScalingGroups.filter(t => {
        return (t.AutoScalingGroupName === d.AutoScalingGroupName);
      }).map(t => { return t.Tags }))
    }

    if (d.InstanceId) {
      ec2Tags = [].concat.apply([], cache.Dimension.Instances.filter(t => {
        return (t.InstanceID === d.InstanceId);
      }).map(t => {

        // Workaround since most instances existed before we started tagging in Litany so they don't
        // have their tags if they're in an ASG. This mess probably needs to stay around for a while.
        let asgTag: AWSTagSet = t.Tags.filter((tag: AWSTag) => { return tag.Key === "aws:autoscaling:groupName" })
        if (asgTag.length > 0) {
          let asgName = asgTag[0].Value;
          t.Tags.push({ Key: 'LitanyAutoScalingGroupName', Value: asgName });

          let ttags: AWSTagSet = [].concat.apply([], cache.Dimension.AutoScalingGroups.filter(tt => {
            return (tt.AutoScalingGroupName === asgName);
          }).map(ttt => {
            return ttt.Tags.filter((tttt: AWSTag) => {
              if (tttt.Key === "Name" || tttt.Key.indexOf("aws:") === 0) {
                return false;
              }
              return true;
            })
          }))
          t.Tags = t.Tags.concat(ttags)
          t.Tags.push({ Key: "LitanyType", Value: "Instance" })
        }

        // Back to Normal
        return t.Tags
      }))
    }

    return this.mergeTags([].concat(asgTags, ec2Tags))
  }

  public async fill() {
    let ec2Get = this.ec2.describeInstances({ MaxResults: 1000 }).promise().then(resp => {
      return [].concat.apply([], resp.Reservations.map(r => {
        return [].concat.apply([], r.Instances.map(i => {
          return { InstanceID: i.InstanceId, Tags: i.Tags }
        }));
      }));
    });

    let asgGet = this.asg.describeAutoScalingGroups().promise().then(resp => {
      return [].concat.apply([], resp.AutoScalingGroups.map(a => {
        return { AutoScalingGroupName: a.AutoScalingGroupName, Tags: a.Tags }
      }));
    });

    return Promise.all([asgGet, ec2Get]).then(d => {
      let cache: NamespaceCache = {
        LastUpdated: new Date(),
        Dimension: {
          AutoScalingGroups: d[0],
          Instances: d[1]
        }
      };
      return cache;
    });

  }
}
