import { SSM, AWSError } from "aws-sdk";
import { PromiseResult } from "aws-sdk/lib/request";

type Indexer = {[key: string]: string};


/**
 * Extract the parameter needed
 * 
 * @param result
 * @return {object}
 */
function extractParameters<T>(parameters: Indexer, result: SSM.GetParametersResult): T {

  console.log('Invoke Extract Parameters, From Parameter Store Results ');

  const parameterStore: { [key: string]: any } = {};

  (result.Parameters || []).forEach(parameter => {

    Object.entries(parameters).forEach(p => {

      if (p[1] === parameter.Name) {

        parameterStore[p[0]] = parameter.Value;
      }

    });

  });

  return parameterStore as T;

}


/**
 * Reuest parameters from aws parameter store
 * 
 * @param parameters 
 * @return {Promise}
 */
function requestParameters(parameters: Indexer, configuration: SSM.Types.ClientConfiguration): Promise<PromiseResult<SSM.GetParametersResult, AWSError>> {

  console.log('Invoke Request Parameter, From Parameter Store');

  const ssm = new SSM(configuration);

  const parametersKey: SSM.Types.GetParametersRequest = {

    Names: Object.values(parameters),

    WithDecryption: true

  };

  return ssm.getParameters(parametersKey).promise();

}


/**
 * Get parameters from parameter store
 * 
 * @return {Promise<>}
 */
export async function getParameterStore<T>(parameters: T, configuration: SSM.Types.ClientConfiguration = { apiVersion: '2014-11-06'}): Promise<T> {

  console.log('Invoke Get Parameter, From Parameter Store');

  try {

    const result = await requestParameters(parameters as any, configuration);

    console.log('Success when getting parameters from parameter store,');

    return extractParameters<T>(parameters as any, result) as T;

  } catch (error) {

    console.log('Failed when getting parameters from parameter store,', error);

    throw { code: 400, message: 'An error occurred when getting parameter from parameter store' }

  }

}