"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
var _eventemitter = require("eventemitter3");
var _Parser = require("stream-json/jsonl/Parser.js");
var _helpers = require("./helpers.js");
var _helper = require("./internal/helper.js");
/*
 * MinIO Javascript Library for Amazon S3 Compatible Cloud Storage, (C) 2016 MinIO, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// TODO: type this

// Base class for three supported configs.
class TargetConfig {
  setId(id) {
    this.Id = id;
  }
  addEvent(newevent) {
    if (!this.Event) {
      this.Event = [];
    }
    this.Event.push(newevent);
  }
  addFilterSuffix(suffix) {
    if (!this.Filter) {
      this.Filter = {
        S3Key: {
          FilterRule: []
        }
      };
    }
    this.Filter.S3Key.FilterRule.push({
      Name: 'suffix',
      Value: suffix
    });
  }
  addFilterPrefix(prefix) {
    if (!this.Filter) {
      this.Filter = {
        S3Key: {
          FilterRule: []
        }
      };
    }
    this.Filter.S3Key.FilterRule.push({
      Name: 'prefix',
      Value: prefix
    });
  }
}

// 1. Topic (simple notification service)
exports.TargetConfig = TargetConfig;
class TopicConfig extends TargetConfig {
  constructor(arn) {
    super();
    this.Topic = arn;
  }
}

// 2. Queue (simple queue service)
exports.TopicConfig = TopicConfig;
class QueueConfig extends TargetConfig {
  constructor(arn) {
    super();
    this.Queue = arn;
  }
}

// 3. CloudFront (lambda function)
exports.QueueConfig = QueueConfig;
class CloudFunctionConfig extends TargetConfig {
  constructor(arn) {
    super();
    this.CloudFunction = arn;
  }
}

// Notification config - array of target configs.
// Target configs can be
// 1. Topic (simple notification service)
// 2. Queue (simple queue service)
// 3. CloudFront (lambda function)
exports.CloudFunctionConfig = CloudFunctionConfig;
class NotificationConfig {
  add(target) {
    let instance;
    if (target instanceof TopicConfig) {
      instance = this.TopicConfiguration ?? (this.TopicConfiguration = []);
    }
    if (target instanceof QueueConfig) {
      instance = this.QueueConfiguration ?? (this.QueueConfiguration = []);
    }
    if (target instanceof CloudFunctionConfig) {
      instance = this.CloudFunctionConfiguration ?? (this.CloudFunctionConfiguration = []);
    }
    if (instance) {
      instance.push(target);
    }
  }
}
exports.NotificationConfig = NotificationConfig;
const buildARN = (partition, service, region, accountId, resource) => {
  return 'arn:' + partition + ':' + service + ':' + region + ':' + accountId + ':' + resource;
};
exports.buildARN = buildARN;
const ObjectCreatedAll = 's3:ObjectCreated:*';
exports.ObjectCreatedAll = ObjectCreatedAll;
const ObjectCreatedPut = 's3:ObjectCreated:Put';
exports.ObjectCreatedPut = ObjectCreatedPut;
const ObjectCreatedPost = 's3:ObjectCreated:Post';
exports.ObjectCreatedPost = ObjectCreatedPost;
const ObjectCreatedCopy = 's3:ObjectCreated:Copy';
exports.ObjectCreatedCopy = ObjectCreatedCopy;
const ObjectCreatedCompleteMultipartUpload = 's3:ObjectCreated:CompleteMultipartUpload';
exports.ObjectCreatedCompleteMultipartUpload = ObjectCreatedCompleteMultipartUpload;
const ObjectRemovedAll = 's3:ObjectRemoved:*';
exports.ObjectRemovedAll = ObjectRemovedAll;
const ObjectRemovedDelete = 's3:ObjectRemoved:Delete';
exports.ObjectRemovedDelete = ObjectRemovedDelete;
const ObjectRemovedDeleteMarkerCreated = 's3:ObjectRemoved:DeleteMarkerCreated';
exports.ObjectRemovedDeleteMarkerCreated = ObjectRemovedDeleteMarkerCreated;
const ObjectReducedRedundancyLostObject = 's3:ReducedRedundancyLostObject';

// put string at least so auto-complete could work

// TODO: type this
exports.ObjectReducedRedundancyLostObject = ObjectReducedRedundancyLostObject;
// Poll for notifications, used in #listenBucketNotification.
// Listening constitutes repeatedly requesting s3 whether or not any
// changes have occurred.
class NotificationPoller extends _eventemitter.EventEmitter {
  constructor(client, bucketName, prefix, suffix, events) {
    super();
    this.client = client;
    this.bucketName = bucketName;
    this.prefix = prefix;
    this.suffix = suffix;
    this.events = events;
    this.ending = false;
  }

  // Starts the polling.
  start() {
    this.ending = false;
    process.nextTick(() => {
      this.checkForChanges();
    });
  }

  // Stops the polling.
  stop() {
    this.ending = true;
  }
  checkForChanges() {
    // Don't continue if we're looping again but are cancelled.
    if (this.ending) {
      return;
    }
    const method = 'GET';
    const queries = [];
    if (this.prefix) {
      const prefix = (0, _helper.uriEscape)(this.prefix);
      queries.push(`prefix=${prefix}`);
    }
    if (this.suffix) {
      const suffix = (0, _helper.uriEscape)(this.suffix);
      queries.push(`suffix=${suffix}`);
    }
    if (this.events) {
      this.events.forEach(s3event => queries.push('events=' + (0, _helper.uriEscape)(s3event)));
    }
    queries.sort();
    let query = '';
    if (queries.length > 0) {
      query = `${queries.join('&')}`;
    }
    const region = this.client.region || _helpers.DEFAULT_REGION;
    this.client.makeRequestAsync({
      method,
      bucketName: this.bucketName,
      query
    }, '', [200], region).then(response => {
      const asm = _Parser.make();
      (0, _helper.pipesetup)(response, asm).on('data', data => {
        // Data is flushed periodically (every 5 seconds), so we should
        // handle it after flushing from the JSON parser.
        let records = data.value.Records;
        // If null (= no records), change to an empty array.
        if (!records) {
          records = [];
        }

        // Iterate over the notifications and emit them individually.
        records.forEach(record => {
          this.emit('notification', record);
        });

        // If we're done, stop.
        if (this.ending) {
          response === null || response === void 0 ? void 0 : response.destroy();
        }
      }).on('error', e => this.emit('error', e)).on('end', () => {
        // Do it again, if we haven't cancelled yet.
        process.nextTick(() => {
          this.checkForChanges();
        });
      });
    }, e => {
      return this.emit('error', e);
    });
  }
}
exports.NotificationPoller = NotificationPoller;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,[encoded data, 18988 characters]