"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
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());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.serve = void 0;
const express_1 = __importDefault(require("express"));
const cors_1 = __importDefault(require("cors"));
const core = __importStar(require("@rockset/core"));
const pathutil_1 = require("@rockset/core/dist/filesystem/pathutil");
const open_1 = __importDefault(require("open"));
const path_1 = __importDefault(require("path"));
const morgan_1 = __importDefault(require("morgan"));
const types_1 = require("@rockset/core/dist/types");
function notEmpty(value) {
    return value !== null && value !== undefined;
}
function serve(port = 3001) {
    return __awaiter(this, void 0, void 0, function* () {
        const app = express_1.default();
        app.use(cors_1.default());
        app.use(morgan_1.default('tiny'));
        app.use(express_1.default.json());
        app.post('/v1/orgs/self/ws/:workspace/lambdas/:queryLambda/versions/:version', (req, res) => __awaiter(this, void 0, void 0, function* () {
            var _a, _b;
            const ws = req.params.workspace;
            const ql = req.params.queryLambda;
            // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
            const params = (_a = req.body) === null || _a === void 0 ? void 0 : _a.parameters;
            const [client, lambda] = yield Promise.all([
                core.main.createClient(),
                core.fileutil.readLambdaFromQualifiedName(pathutil_1.getQualifiedName(ws, ql)),
            ]);
            try {
                const result = yield client.queries.query({
                    sql: {
                        query: lambda.sql,
                        parameters: types_1.mergeParameters((_b = lambda.config.default_parameters) !== null && _b !== void 0 ? _b : [], params),
                    },
                });
                res.send(result);
            }
            catch (e) {
                console.error('Error during execution: ', e);
                res.status(400);
                res.send(e);
            }
        }));
        app.post('/validate', (req, res) => __awaiter(this, void 0, void 0, function* () {
            var _c;
            // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
            const param = (_c = req.body) === null || _c === void 0 ? void 0 : _c.param;
            const client = yield core.main.createClient();
            try {
                yield client.queries.validate({
                    sql: {
                        query: `Select :"${param.name}"`,
                        parameters: [param],
                    },
                });
                res.send({ success: true });
            }
            catch (e) {
                console.error(e);
                res.status(400);
                res.send(e);
            }
        }));
        app.get('/lambdas', (req, res) => __awaiter(this, void 0, void 0, function* () {
            try {
                const [entityNames, { api_server: apiserver }, srcPath,] = yield Promise.all([
                    core.main.listEntityNames(),
                    core.auth.getAuthProfile(),
                    core.fileutil.getSrcPath(),
                ]);
                const lambdaEntities = (yield Promise.all(entityNames.lambdas.map(([name]) => __awaiter(this, void 0, void 0, function* () {
                    try {
                        return yield core.fileutil.readLambdaFromQualifiedName(name);
                    }
                    catch (e) {
                        return null;
                    }
                })))).filter(notEmpty);
                const lambdas = lambdaEntities.map((entity) => ({
                    path: core.pathutil.getLambdaPathsFromEntity(srcPath, entity),
                    name: entity.name,
                    ws: entity.ws,
                    sql: entity.sql,
                    default_parameters: entity.config.default_parameters,
                }));
                res.send({ lambdas, apiserver });
            }
            catch (e) {
                console.error(e);
                res.status(500);
                res.send(e);
            }
        }));
        app.use(express_1.default.static(path_1.default.join(__dirname, 'ui')));
        app.get('/*', (req, res) => {
            res.sendFile(path_1.default.join(__dirname, 'ui', 'index.html'));
        });
        app.listen(port, () => console.log(`QL dev server listening at http://localhost:${port}`));
        yield open_1.default(`http://localhost:${port}`);
    });
}
exports.serve = serve;
