// Licensed to the Apache Software Foundation (ASF) under one or more contributor
// license agreements; and to You under the Apache License, Version 2.0.

'use strict'

const test = require('ava')
const Activations = require('../../lib/activations.js')
const Client = require('../../lib/client.js')
const Utils = require('./utils.js')
const options = Utils.autoOptions();

const envParams = ['API_KEY', 'API_HOST', 'NAMESPACE']

// check that mandatory configuration properties are available
envParams.forEach(key => {
  const param = `__OW_${key}`
  if (!process.env.hasOwnProperty(param)) {
    throw new Error(`Missing ${param} environment parameter`)
  }
})

const NAMESPACE = process.env.__OW_NAMESPACE

test('list all activations', t => {
  const activations = new Activations(new Client(options))
  return activations.list().then(result => {
    t.true(Array.isArray(result))
    result.forEach(r => t.is(r.namespace, NAMESPACE))
    t.pass()
  }).catch(err => {
    console.log(err)
    t.fail()
  })
})

test('retrieve individual activations', t => {
  const activations = new Activations(new Client(options))
  return activations.list().then(result => {
    t.true(Array.isArray(result))
    return Promise.all(result.map(r => activations.get({activation: r.activationId})))
  }).catch(err => {
    console.log(err)
    t.fail()
  })
})

test('retrieve individual activation logs', t => {
  const activations = new Activations(new Client(options))
  return activations.list().then(result => {
    t.true(Array.isArray(result))
    return Promise.all(result.map(r => activations.logs({activation: r.activationId})))
  }).catch(err => {
    console.log(err)
    t.fail()
  })
})

test('retrieve individual activation result', t => {
  const activations = new Activations(new Client(options))
  return activations.list().then(result => {
    t.true(Array.isArray(result))
    return Promise.all(result.map(r => activations.result({activation: r.activationId})))
  }).catch(err => {
    console.log(err)
    t.fail()
  })
})
