import AWS = require('aws-sdk');
import { CloudwatchMetricStructure } from '../interfaces/cloudwatch';
import { SensuTagSet, SensuValueSet, SensuMetricStructure } from '../interfaces/sensu';
import { AWSTags } from '../cache';

export class Metric {
  raw: CloudwatchMetricStructure;
  timestamp: Date;
  namespace: string;
  tagger: AWSTags;
  unit: string;

  constructor(data: CloudwatchMetricStructure) {
    if (!data.Metric.Datapoints || data.Metric.Datapoints.length === 0) {
      throw Error('unimplemented method');
    } else {
      this.raw = data;
      this.timestamp = (data.Metric.Datapoints[0].Timestamp as Date);
      this.unit = (data.Metric.Datapoints[0].Unit as string);
      this.namespace = data.Definition.Namespace;
      this.tagger = AWSTags.init
    }
  }

  getTagSet(): SensuTagSet {
    let tagSet: SensuTagSet = {};

    for (let j = 0; j < this.raw.Definition.Dimensions.length; j++) {
      tagSet[this.raw.Definition.Dimensions[j].Name] =
        this.raw.Definition.Dimensions[j].Value;
    }

    tagSet.Namespace = this.raw.Definition.Namespace;
    tagSet.AwsAccountId = process.env.AWSAccountId as string;
    tagSet.Stage = process.env.STAGE as string;
    tagSet.Region = process.env.AWS_REGION as string;
    tagSet.Environment = process.env.PROJECT as string;

    if (this.requiresTagCache() && this.hasTagCache()) {
      let awsTags = this.tagger.getTags(tagSet.Namespace, this.raw.Definition.Dimensions);
      for (let tag of Object.keys(awsTags)) {
        tagSet[tag] = awsTags[tag];
      }
    }

    return tagSet;
  }

  getValueSet(): SensuValueSet {
    let values: SensuValueSet = {};

    for (let key of Object.keys(this.raw.Metric.Datapoints[0])) {
      if (key !== 'Timestamp' && key !== 'Unit') {
        values[key] = (this.raw.Metric.Datapoints[0] as AWS.CloudWatch.Types.DatapointValueMap)[key];
      }
    }

    return values;
  }

  requiresTagCache(): boolean {
    return (Object.keys(this.tagger.taggableNamespaces).indexOf(this.raw.Definition.Namespace) > -1)
  }

  hasTagCache(): boolean {
    return (Object.keys(this.tagger.getTags(this.raw.Definition.Namespace, this.raw.Definition.Dimensions)).length > 0);
  }

  toSensuPoint(): SensuMetricStructure {
    let data = {
      source: 'cloudwatch',
      series: this.raw.Metric.Label,
      tags: this.getTagSet(),
      timestamp: this.timestamp,
      unit: this.unit,
      values: this.getValueSet()
    }
    return data;
  }
}
