#!/usr/bin/env node
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const api_client_1 = require("@cross-lab-project/api-client");
const cookie_parser_1 = __importDefault(require("cookie-parser"));
const express_1 = __importDefault(require("express"));
const express_async_handler_1 = __importDefault(require("express-async-handler"));
const express_winston_1 = __importDefault(require("express-winston"));
const nunjucks_1 = __importDefault(require("nunjucks"));
const path_1 = __importDefault(require("path"));
const winston_1 = __importDefault(require("winston"));
const admin_1 = require("./admin");
const config_1 = require("./config");
const experiment_1 = require("./experiment");
const thk_1 = require("./thk");
const utils_1 = require("./utils");
const content_path = config_1.config.NODE_ENV === "development"
    ? "src/content"
    : path_1.default.dirname(__filename) + "/content";
const nunjucks_configuration = {
    autoescape: true,
    noCache: config_1.config.NODE_ENV === "development",
};
const languages = ["en", "de"];
const renderPage = (0, utils_1.renderPageInit)(content_path, config_1.config.DEFAULT_LANGUAGE);
const app = (0, express_1.default)();
const logger = winston_1.default.createLogger({
    transports: [new winston_1.default.transports.Console()],
    format: winston_1.default.format.combine(winston_1.default.format.colorize(), winston_1.default.format.simple()),
});
app.set("etag", config_1.config.NODE_ENV !== "development");
app.use((_req, res, next) => {
    res.removeHeader("X-Powered-By");
    next();
});
app.use(express_1.default.urlencoded({ extended: true }));
app.use((0, cookie_parser_1.default)());
nunjucks_1.default.configure(content_path + "/templates", {
    ...nunjucks_configuration,
    express: app,
});
app.use("/img", express_1.default.static(path_1.default.join(content_path, "img")));
if (config_1.config.NODE_ENV === "development") {
    // When developing, we dynamically transform the css files with postcss
    const { postcss_transform } = require("./debug_utils");
    app.use("/css", postcss_transform(path_1.default.join(content_path, "css")));
}
else {
    // For production, we use precompiled css files
    app.use("/css", express_1.default.static(path_1.default.join(content_path, "css")));
}
app.use(express_winston_1.default.logger({
    winstonInstance: logger,
    meta: true,
    msg: "HTTP {{req.method}} {{req.url}}",
    expressFormat: true,
    colorize: true,
    ignoreRoute: function () {
        return false;
    }, // optional: allows to skip some log messages based on request and/or response
}));
async function handle_login(req, res, next) {
    let loggedIn = false;
    for (const method of ["tui", "local"]) {
        try {
            await req.apiClient.login(req.body.username, req.body.password, {
                method,
            });
            res.cookie("token", req.apiClient.accessToken, {
                secure: true,
                httpOnly: true,
                sameSite: "strict",
            });
            loggedIn = true;
            break;
        }
        catch (error) {
            logger.log("info", `Could not login with method '${method}`);
        }
    }
    if (loggedIn) {
        try {
            req.user = await req.apiClient.getIdentity();
            if (req.query.redirect) {
                res.redirect(303, req.query.redirect);
            }
            else {
                res.redirect(303, "index.html");
            }
        }
        catch (e) {
            logger.warn(e);
            res.clearCookie("token");
            next();
        }
    }
    else {
        res.clearCookie("token");
        logger.warn("user could not be logged in!");
        next();
    }
}
async function handle_logout(req, res, _next) {
    res.clearCookie("token");
    if (req.query.redirect) {
        res.redirect(303, req.query.redirect);
    }
    else {
        res.redirect(303, "/index.html");
    }
}
app.use("/", (0, express_async_handler_1.default)(async (req, res, next) => {
    req.apiClient = new api_client_1.APIClient(config_1.config.API_URL);
    req.user = undefined;
    // handle token query parameter
    if (req.query.token && typeof req.query.token === "string") {
        req.apiClient.accessToken = req.query.token;
        res.cookie("token", req.query.token, {
            secure: true,
            httpOnly: true,
        });
        req.user = {
            ...(await req.apiClient.getIdentity()),
            token: req.query.token,
        };
    }
    else if (req.cookies.token) {
        try {
            req.apiClient.accessToken = req.cookies.token;
            req.user = {
                ...(await req.apiClient.getIdentity()),
                token: req.cookies.token,
            };
        }
        catch (e) {
            logger.info(e);
            res.clearCookie("token");
        }
    }
    next();
}));
for (const language of languages) {
    app.post("/" + language + "/login.html", (0, express_async_handler_1.default)(handle_login));
    app.get("/" + language + "/logout.html", (0, express_async_handler_1.default)(handle_logout));
    app.use("/" + language + "/admin/", (0, admin_1.admin_router)(language, renderPage, logger));
    app.use("/" + language + "/", (0, experiment_1.experiment_router)(language, renderPage, logger));
    app.use("/" + language + "/", (0, thk_1.thk_router)(language, renderPage, logger));
    app.get("/" + language + "/", (0, express_async_handler_1.default)(async (req, res) => {
        await renderPage("index", language, res, req.user);
    }));
    app.use("/" + language + "/", (0, express_async_handler_1.default)(async (req, res) => {
        await renderPage(req.path, language, res, req.user);
    }));
}
app.use("/", function (req, res) {
    const selected_language = req.acceptsLanguages(languages) || config_1.config.DEFAULT_LANGUAGE;
    res.redirect(307, "/" + selected_language + req.originalUrl);
});
app.use(express_winston_1.default.errorLogger({ winstonInstance: logger }));
if (config_1.config.NODE_ENV === "development") {
    // When developing, we start a browserSync server after listen
    const { start_browserSync } = require("./debug_utils");
    const server = app.listen(() => start_browserSync(server.address().port));
}
else {
    // Just listen on the configured port
    app.listen(config_1.config.PORT);
}
//# sourceMappingURL=index.js.map