"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());
    });
};
const internal = require("./internal");
const external = require("./external");
const csvParser = require("../../../utilities/csvParser");
const { isExternalTable, isSQL } = require("../../../integrations/utils");
const { getDatasourceParams } = require("../../../db/utils");
const { getAppDB } = require("@devlego/backend-core/context");
const { getTable, getAllInternalTables } = require("./utils");
const { events } = require("@devlego/backend-core");
function pickApi({ tableId, table }) {
    if (table && !tableId) {
        tableId = table._id;
    }
    if (table && table.type === "external") {
        return external;
    }
    else if (tableId && isExternalTable(tableId)) {
        return external;
    }
    return internal;
}
// covers both internal and external
exports.fetch = function (ctx) {
    return __awaiter(this, void 0, void 0, function* () {
        const db = getAppDB();
        const internal = yield getAllInternalTables();
        const externalTables = yield db.allDocs(getDatasourceParams("plus", {
            include_docs: true,
        }));
        const external = externalTables.rows.flatMap(tableDoc => {
            let entities = tableDoc.doc.entities;
            if (entities) {
                return Object.values(entities).map(entity => (Object.assign(Object.assign({}, entity), { type: "external", sourceId: tableDoc.doc._id, sql: isSQL(tableDoc.doc) })));
            }
            else {
                return [];
            }
        });
        ctx.body = [...internal, ...external];
    });
};
exports.find = function (ctx) {
    return __awaiter(this, void 0, void 0, function* () {
        const tableId = ctx.params.tableId;
        ctx.body = yield getTable(tableId);
    });
};
exports.save = function (ctx) {
    return __awaiter(this, void 0, void 0, function* () {
        const appId = ctx.appId;
        const table = ctx.request.body;
        const importFormat = table.dataImport && table.dataImport.csvString ? "csv" : undefined;
        const savedTable = yield pickApi({ table }).save(ctx);
        if (!table._id) {
            yield events.table.created(savedTable);
        }
        else {
            yield events.table.updated(savedTable);
        }
        if (importFormat) {
            yield events.table.imported(savedTable, importFormat);
        }
        ctx.status = 200;
        ctx.message = `Table ${table.name} saved successfully.`;
        ctx.eventEmitter &&
            ctx.eventEmitter.emitTable(`table:save`, appId, savedTable);
        ctx.body = savedTable;
    });
};
exports.destroy = function (ctx) {
    return __awaiter(this, void 0, void 0, function* () {
        const appId = ctx.appId;
        const tableId = ctx.params.tableId;
        const deletedTable = yield pickApi({ tableId }).destroy(ctx);
        yield events.table.deleted(deletedTable);
        ctx.eventEmitter &&
            ctx.eventEmitter.emitTable(`table:delete`, appId, deletedTable);
        ctx.status = 200;
        ctx.table = deletedTable;
        ctx.body = { message: `Table ${tableId} deleted.` };
    });
};
exports.bulkImport = function (ctx) {
    return __awaiter(this, void 0, void 0, function* () {
        const tableId = ctx.params.tableId;
        yield pickApi({ tableId }).bulkImport(ctx);
        // right now we don't trigger anything for bulk import because it
        // can only be done in the builder, but in the future we may need to
        // think about events for bulk items
        ctx.status = 200;
        ctx.body = { message: `Bulk rows created.` };
    });
};
exports.validateCSVSchema = function (ctx) {
    return __awaiter(this, void 0, void 0, function* () {
        // tableId being specified means its an import to an existing table
        const { csvString, schema = {}, tableId } = ctx.request.body;
        let existingTable;
        if (tableId) {
            existingTable = yield getTable(tableId);
        }
        let result = yield csvParser.parse(csvString, schema);
        if (existingTable) {
            result = csvParser.updateSchema({ schema: result, existingTable });
        }
        ctx.body = { schema: result };
    });
};
