"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
let { merge } = require("lodash");
let env = require("../environment");
const AWS_REGION = env.AWS_REGION ? env.AWS_REGION : "eu-west-1";
exports.AWS_REGION = AWS_REGION;
const TableInfo = {
    API_KEYS: {
        name: "beta-api-key-table",
        primary: "pk",
    },
    USERS: {
        name: "prod-budi-table",
        primary: "pk",
        sort: "sk",
    },
};
let docClient = null;
class Table {
    constructor(tableInfo) {
        if (!tableInfo.name || !tableInfo.primary) {
            throw "Table info must specify a name and a primary key";
        }
        this._name = tableInfo.name;
        this._primary = tableInfo.primary;
        this._sort = tableInfo.sort;
    }
    get({ primary, sort, otherProps }) {
        return __awaiter(this, void 0, void 0, function* () {
            let params = {
                TableName: this._name,
                Key: {
                    [this._primary]: primary,
                },
            };
            if (this._sort && sort) {
                params.Key[this._sort] = sort;
            }
            if (otherProps) {
                params = merge(params, otherProps);
            }
            let response = yield docClient.get(params).promise();
            return response.Item;
        });
    }
    update({ primary, sort, expression, condition, names, values, exists, otherProps, }) {
        return __awaiter(this, void 0, void 0, function* () {
            let params = {
                TableName: this._name,
                Key: {
                    [this._primary]: primary,
                },
                ExpressionAttributeNames: names,
                ExpressionAttributeValues: values,
                UpdateExpression: expression,
            };
            if (condition) {
                params.ConditionExpression = condition;
            }
            if (this._sort && sort) {
                params.Key[this._sort] = sort;
            }
            if (exists) {
                params.ExpressionAttributeNames["#PRIMARY"] = this._primary;
                if (params.ConditionExpression) {
                    params.ConditionExpression += " AND ";
                }
                params.ConditionExpression += "attribute_exists(#PRIMARY)";
            }
            if (otherProps) {
                params = merge(params, otherProps);
            }
            return docClient.update(params).promise();
        });
    }
    put({ item, otherProps }) {
        return __awaiter(this, void 0, void 0, function* () {
            if (item[this._primary] == null ||
                (this._sort && item[this._sort] == null)) {
                throw "Cannot put item without primary and sort key (if required)";
            }
            let params = {
                TableName: this._name,
                Item: item,
            };
            if (otherProps) {
                params = merge(params, otherProps);
            }
            return docClient.put(params).promise();
        });
    }
}
exports.init = endpoint => {
    let AWS = require("aws-sdk");
    AWS.config.update({
        region: AWS_REGION,
    });
    let docClientParams = {
        correctClockSkew: true,
    };
    if (endpoint) {
        docClientParams.endpoint = endpoint;
    }
    else if (env.DYNAMO_ENDPOINT) {
        docClientParams.endpoint = env.DYNAMO_ENDPOINT;
    }
    docClient = new AWS.DynamoDB.DocumentClient(docClientParams);
};
exports.apiKeyTable = new Table(TableInfo.API_KEYS);
exports.userTable = new Table(TableInfo.USERS);
if (env.isProd()) {
    exports.init(`https://dynamodb.${AWS_REGION}.amazonaws.com`);
}
else {
    env._set("AWS_ACCESS_KEY_ID", "KEY_ID");
    env._set("AWS_SECRET_ACCESS_KEY", "SECRET_KEY");
    exports.init("http://localhost:8333");
}
