"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getDomainConfigurations = exports.getConfiguration = exports.patchConfig = exports.serveIndex = exports.getSettings = exports.setSettings = exports.getPluginManifest = exports.getJobsStatus = exports.getJobs = exports.patchJob = exports.addJob = exports.getTraitById = exports.getEventByBasename = exports.getCaptureByBasename = exports.patchCapture = exports.getCapturesList = exports.listPlugins = void 0;
const path_1 = __importDefault(require("path"));
const schemas_1 = require("../../../schemas/schemas");
/**
 * List all available plugin names.
 *
 * @route GET /plugins
 * @returns {Array<string>|Error(500)} - List of plugin names or 500 error on failure.
 */
const listPlugins = async (req, res, filesystem, logger) => {
    if (req.method !== 'GET') {
        res.status(405).send('Method Not Allowed');
        return;
    }
    try {
        const plugins = (await filesystem.listPluginBasenames()).map(value => path_1.default.basename(value));
        res.send(plugins);
    }
    catch (error) {
        logger.error(`Failed to list plugins: ${error} ${error.stack}`);
        res.status(500).send(error.message);
    }
};
exports.listPlugins = listPlugins;
/**
 * Retrieve list of all available captures.
 *
 * @route GET /captures
 * @returns {Array<Capture>|Error(500)} - List of capture metadata or 500 error.
 */
const getCapturesList = async (req, res, filesystem, logger) => {
    if (req.method !== 'GET') {
        res.status(405).send('Method Not Allowed');
        return;
    }
    try {
        // Fetch list of captures
        res.json(await filesystem.listCaptureBasenames());
    }
    catch (error) {
        logger.error(`Failed to list captures: ${error}`);
        res.status(500).send(error.message);
    }
};
exports.getCapturesList = getCapturesList;
/**
 * Update metadata for a given capture.
 *
 * @route PATCH /captures/:basename
 * @body PatchCaptureAction
 * @returns {Status(200)|Error(500)} - 200 on success, 500 on validation or server error.
 */
const patchCapture = async (req, res, filesystem, logger) => {
    if (req.method !== 'PATCH') {
        res.status(405).send('Method Not Allowed');
        return;
    }
    try {
        const capture = schemas_1.PatchCaptureActionSchema.parse(req.body);
        const { basename } = req.params;
        await filesystem.patchCapture(basename, capture.name);
        res.sendStatus(200);
    }
    catch (error) {
        logger.error(`Failed to patch capture: ${error}`);
        res.status(500).send(error.message);
    }
};
exports.patchCapture = patchCapture;
/**
 * Get a specific capture by ID.
 *
 * @route GET /captures/:basename
 * @returns {Capture|Status(404)|Error(500)} - Capture object, 404 if not found, 500 on error.
 */
const getCaptureByBasename = async (req, res, filesystem, logger) => {
    const { basename } = req.params;
    if (req.method !== 'GET') {
        res.status(405).send('Method Not Allowed');
        return;
    }
    try {
        const capture = await filesystem.getCapture(basename);
        const events = await filesystem.listEventBasenames(basename);
        if (capture)
            res.json({ "capture": capture, "events": events });
        else
            res.sendStatus(404);
    }
    catch (error) {
        logger.error(`Failed to get capture ${basename}: ${error}`);
        res.status(500).send(error.message);
    }
};
exports.getCaptureByBasename = getCaptureByBasename;
/**
 * Get a specific event from a capture by its ID.
 *
 * @route GET /captures/:capture_basename/events/:event_basename
 * @returns {CollectedEvent|Status(404)|Error(500)} - Event object or 404/500.
 */
const getEventByBasename = async (req, res, filesystem, logger) => {
    if (req.method !== 'GET') {
        res.status(405).send('Method Not Allowed');
        return;
    }
    const { capture_basename, event_basename } = req.params;
    try {
        const event = await filesystem.getEvent(capture_basename, event_basename);
        if (event)
            res.json(event);
        else
            res.sendStatus(404);
    }
    catch (error) {
        logger.error(`Failed to get event ${event_basename} (capture: ${capture_basename}): ${error}`);
        res.status(500).send(error.message);
    }
};
exports.getEventByBasename = getEventByBasename;
/**
 * Retrieve a gathered trait by ID from an event in a capture.
 *
 * @route GET /captures/:capture_basename/events/:event_basename/traits/:traitId
 * @returns {GatheredTrait|Status(404)|Error(500)} - Trait data or 404/500.
 */
const getTraitById = async (req, res, filesystem, logger) => {
    if (req.method !== 'GET') {
        res.status(405).send('Method Not Allowed');
        return;
    }
    try {
        const { capture_basename, event_basename, traitId } = req.params;
        const trait = await filesystem.getGatheredTrait(capture_basename, event_basename, traitId);
        if (trait)
            res.json(trait);
        else
            res.sendStatus(404);
    }
    catch (error) {
        logger.error(`Failed to get trait: ${error}`);
        res.status(500).send(error.message);
    }
};
exports.getTraitById = getTraitById;
/**
 * Adds job to job queue.
 *
 * @route POST /jobs/job
 * @body JobRequest
 * @returns {Status(202)|Error(500)} - 202 on success + job request body, 500 on error.
 */
const addJob = (req, res, settings, jobQueue, logger) => {
    if (req.method !== 'POST') {
        res.status(405).send('Method Not Allowed');
        return;
    }
    logger.debug("adding job");
    try {
        const job_request = schemas_1.JobRequestSchema.parse(req.body);
        const request = jobQueue.addJob(job_request);
        if (request[1]) {
            request[1].catch((error) => {
                logger.error(`Job failed: ${error}`);
            });
        }
        res.sendStatus(202).send(request[0]);
    }
    catch (error) {
        logger.error(`Failed to add job: ${error}`);
        res.status(500).send(error.message);
    }
};
exports.addJob = addJob;
/**
 * Patches currently running job.
 *
 * @route PATCH jobs/current
 * @body JobChangeRequest
 * @returns { Status(202) | Error(500) } - 202 on success
 */
const patchJob = (req, res, jobQueue, logger) => {
    if (req.method !== 'PATCH') {
        res.status(405).send('Method Not Allowed');
        return;
    }
    logger.debug("halting current job");
    const current_job = jobQueue.getCurrentJob();
    if (current_job) {
        current_job.halted = true;
        res.sendStatus(202);
    }
    else {
        res.sendStatus(500).send("No job found to stop");
    }
};
exports.patchJob = patchJob;
/**
 * Get job queue state.
 *
 * @route GET /jobs
 * @returns {{ status: Array<Job> }|Error(500)} - Application job queue state or 500 error.
 */
const getJobs = (req, res, jobQueue, logger) => {
    if (req.method !== 'GET') {
        res.status(405).send('Method Not Allowed');
        return;
    }
    try {
        // Return app state + debug information
        res.json({ current: jobQueue.getCurrentJob(), count: jobQueue.getCount() });
    }
    catch (error) {
        logger.error(error.message);
        res.status(500).send(error.message);
    }
};
exports.getJobs = getJobs;
/**
 * Get the status of the current running job.
 *
 * @route GET /jobs/current
 * @returns {string|Error(500)} - Job status as an unparsed JSON string or 500 error.
 */
const getJobsStatus = async (req, res, filesystem, logger) => {
    if (req.method !== 'GET') {
        res.status(405).send('Method Not Allowed');
        return;
    }
    try {
        const log = await filesystem.getJobLog();
        res.json(log);
    }
    catch (error) {
        logger.error(error.message);
        res.status(500).send(error.message);
    }
};
exports.getJobsStatus = getJobsStatus;
/**
 * Get the manifest for a given plugin by name.
 *
 * @route GET /plugins/:name
 * @returns {object|Error(500)} - Plugin manifest JSON or 500 error.
 */
const getPluginManifest = async (req, res, filesystem, logger) => {
    if (req.method !== 'GET') {
        res.status(405).send('Method Not Allowed');
        return;
    }
    try {
        const { name } = req.params;
        const plugin = await filesystem.getPluginManifest(name); //Argument of type 'string | string[]' is not assignable to parameter of type 'string'. Type 'string[]' is not assignable to type 'string'.ts(2345)
        res.json(plugin);
    }
    catch (error) {
        logger.error(error.message);
        res.status(500).send(error.message);
    }
};
exports.getPluginManifest = getPluginManifest;
/**
 * Set app settings
 *
 * @route POST /settings
 * @body AppSettings
 * @returns {Status(204)|Error(500)} - 204 on success, 500 on error.
 */
const setSettings = async (req, res, settings, logger) => {
    if (req.method !== 'POST') {
        res.status(405).send('Method Not Allowed');
        return;
    }
    logger.info("Setting app settings.");
    try {
        const parsed = (0, schemas_1.AppSettingsSchemaFactory)(await settings.getPluginsDirectory(), await settings.getCapturesDirectory()).parse(req.body);
        settings.setSettings(parsed);
        await settings.saveSettings();
        res.sendStatus(204);
    }
    catch (error) {
        logger.error(error.message);
        res.status(500).send(error.message);
    }
};
exports.setSettings = setSettings;
/**
 * Get global app settings.
 *
 * @route GET /settings
 * @returns {object|Error(500)} - App settings JSON or 500 error.
 */
const getSettings = async (req, res, settings, logger) => {
    if (req.method !== 'GET') {
        res.status(405).send('Method Not Allowed');
        return;
    }
    try {
        res.json(await settings.getSettings());
    }
    catch (error) {
        logger.error(error.message);
        res.status(500).send(error.message);
    }
};
exports.getSettings = getSettings;
/**
 * Serve an index file from the specified root path.
 *
 * @route GET /*
 * @returns {HTML} - Sends the index HTML file.
 */
// how do i setup this type definition without triggering eslint@typescript-eslint/no-empty-object-type
const serveIndex = (req, res, root_directory, filename) => {
    if (req.method !== 'GET') {
        res.status(405).send('Method Not Allowed');
        return;
    }
    const { name } = req.params;
    if (name && name.length > 0) {
        res.sendFile(path_1.default.join(name, filename ?? "index.html"), { root: root_directory });
        return;
    }
    res.sendFile(path_1.default.join(root_directory, filename ?? "index.html"));
};
exports.serveIndex = serveIndex;
/**
 * Set configurations. Expects a dictionary of changes.
 *
 * @route PATCH /config/:domain/
 * @body AppSettings
 * @returns {Status(204)|Error(500)} - 204 on success, 500 on error.
 */
const patchConfig = (req, res, config, logger) => {
    if (req.method !== 'PATCH') {
        res.status(405).send('Method Not Allowed');
        return;
    }
    logger.info("Setting app settings.");
    try {
        const parsed = req.body;
        const { domain } = req.params;
        const entries = Object.entries(parsed);
        if (entries && entries.length > 0) {
            for (const [key, value] of entries) {
                if (config.hasConfig(domain, key)) {
                    if (config.isString(domain, key)) {
                        config.setConfig(domain, key, value);
                    }
                    else if (config.isNumber(domain, key)) {
                        config.setConfig(domain, key, value);
                    }
                    else if (config.isBool(domain, key)) {
                        config.setConfig(domain, key, value);
                    }
                }
            }
        }
    }
    catch (error) {
        logger.error(error.message);
        res.status(500).send(error.message);
    }
};
exports.patchConfig = patchConfig;
/**
 * Get a specific configuration.
 *
 * @route GET /configuration/:domain/:name/:default
 * @returns {object|Error(500)} - App settings JSON or 500 error.
 */
const getConfiguration = (req, res, config) => {
    if (req.method !== 'GET') {
        res.status(405).send('Method Not Allowed');
        return;
    }
    const { domain, name, is_default } = req.params;
    res.send(config.getConfig(domain, name, (is_default != undefined && is_default === "default")));
};
exports.getConfiguration = getConfiguration;
/**
 * Get configurations for a given domain.
 *
 * @route GET /configuration/:domain
 * @returns {object|Error(500)} - App settings JSON or 500 error.
 */
const getDomainConfigurations = (req, res, config) => {
    if (req.method !== 'GET') {
        res.status(405).send('Method Not Allowed');
        return;
    }
    const { domain } = req.params;
    if (!domain) {
        res.status(500).send("Domain was not specified");
    }
    const configurations = config.listConfigurations(domain);
    res.send(configurations);
    return;
};
exports.getDomainConfigurations = getDomainConfigurations;
//# sourceMappingURL=route_handlers.js.map