import { Context } from "aws-lambda";
import { Iot, STS } from "aws-sdk";
import * as uuid from "uuid";
import { initCommonMiddlewares } from "../middlewares";

const signUrl = require("aws-device-gateway-signed-url");

interface IEvent {
  user: {
    username;
  };
}

interface IResult {
  topic: string;
  endpoint: string;
  expiration: number;
}

const {
  NOTIFICATION_ROLE_ARN,
  REGION,
  ROLE_SESSION_NAME_PREFIX,
  TOPIC_PREFIX,
  SESSION_EXPIRATION,
} = process.env;

const iot = new Iot();
const sts = new STS();

async function awsHandler(event: IEvent, context: Context): Promise<IResult> {
  const {
    user: { username },
  } = event;
  const topic = `${TOPIC_PREFIX}/${username}`;

  const accessData = await getTemporaryIotAccessData(topic);

  const now = Math.round(new Date().getTime() / 1000);
  const expiration = now + parseInt(SESSION_EXPIRATION);

  return {
    topic,
    endpoint: signUrl(accessData),
    expiration,
  };
}

/**
 * create temporary access data for direct resource subscription on specific dynamo-topic.
 */
async function getTemporaryIotAccessData(topic: string) {
  // @todo: cache this
  const { endpointAddress } = await iot
    .describeEndpoint({
      endpointType: "iot:Data-ATS",
    })
    .promise();

  const sessionDuration = parseInt(SESSION_EXPIRATION);

  const {
    Credentials: { AccessKeyId, SecretAccessKey, SessionToken },
  } = await sts
    .assumeRole({
      RoleArn: NOTIFICATION_ROLE_ARN,
      RoleSessionName: `${ROLE_SESSION_NAME_PREFIX}_${uuid()}`,
    })
    .promise();

  return {
    endpoint: endpointAddress,
    regionName: REGION,
    accessKey: AccessKeyId,
    secretKey: SecretAccessKey,
    sessionToken: SessionToken,
    expires: sessionDuration,
  };
}

export const handler = initCommonMiddlewares(awsHandler);
