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

export class S3Tags extends Cacher {

  s3: AWS.S3;

  constructor() {
    super()
    this.s3 = new AWS.S3();
  }

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

    s3Tags = [].concat.apply([], cache.Dimension.Buckets.filter(t => {
      return (t.BucketName === d.BucketName);
    }).map(t => { return t.Tags }))

    return this.mergeTags(s3Tags);
  }

  public async fill() {

    let buckets: { BucketName: string, Tags: AWSTagSet }[] = [];
    let tagPromises: Promise<void>[] = [];

    await new Promise((resolve, reject) => {
      this.s3.listBuckets().eachPage((err: any, data) => {
        if (err) {
          console.log(err);
          reject();
          return false;
        }

        if (data === null) {
          resolve();
          return true;
        }

        for (let bucket of data.Buckets) {
          buckets.push({ BucketName: bucket.Name, Tags: [] });
        }
        return true;
      });
    });

    for (let bucket of buckets) {
      tagPromises.push(this.s3.getBucketTagging({ Bucket: bucket.BucketName }).promise().then(data => {
        bucket.Tags = data.TagSet;
        bucket.Tags.push({ Key: 'BucketName', Value: bucket.BucketName }) // Never be empty
      }).catch(() => {
        /* no-op, s3 sdk throws exception on empty tagset */
        bucket.Tags.push({ Key: 'BucketName', Value: bucket.BucketName }) // Never be empty
      }))
    }

    return Promise.all(tagPromises).then(() => {
      let cache: NamespaceCache = {
        LastUpdated: new Date(),
        Dimension: {
          Buckets: buckets,
        }
      };
      return cache;
    });
  }
}
