"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 (k !== "default" && 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 });
const express_1 = require("express");
const express_async_handler_1 = __importDefault(require("express-async-handler"));
const database_1 = __importDefault(require("../database"));
const constants_1 = require("../constants");
const exceptions_1 = require("../exceptions");
const AssetsService = __importStar(require("../services/assets"));
const uuid_validate_1 = __importDefault(require("uuid-validate"));
const lodash_1 = require("lodash");
const storage_1 = __importDefault(require("../storage"));
const router = express_1.Router();
router.get('/:pk', 
// Check if file exists
express_async_handler_1.default((req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
    const id = req.params.pk;
    /**
     * This is a little annoying. Postgres will error out if you're trying to search in `where`
     * with a wrong type. In case of directus_files where id is a uuid, we'll have to verify the
     * validity of the uuid ahead of time.
     * @todo move this to a validation middleware function
     */
    const isValidUUID = uuid_validate_1.default(id, 4);
    if (isValidUUID === false)
        throw new exceptions_1.ForbiddenException();
    const file = yield database_1.default
        .select('id', 'storage', 'filename_disk')
        .from('directus_files')
        .where({ id })
        .first();
    if (!file)
        throw new exceptions_1.ForbiddenException();
    const { exists } = yield storage_1.default.disk(file.storage).exists(file.filename_disk);
    if (!exists)
        throw new exceptions_1.ForbiddenException();
    return next();
})), 
// Validate query params
express_async_handler_1.default((req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
    const defaults = { asset_shortcuts: '[]', asset_generation: 'all' };
    const assetSettings = (yield database_1.default
        .select('asset_shortcuts', 'asset_generation')
        .from('directus_settings')
        .first()) || defaults;
    const transformation = lodash_1.pick(req.query, constants_1.ASSET_GENERATION_QUERY_KEYS);
    if (transformation.hasOwnProperty('key') && Object.keys(transformation).length > 1) {
        throw new exceptions_1.InvalidQueryException(`You can't combine the "key" query parameter with any other transformation.`);
    }
    const systemKeys = constants_1.SYSTEM_ASSET_WHITELIST.map((transformation) => transformation.key);
    const allKeys = [
        ...systemKeys,
        ...assetSettings.asset_shortcuts.map((transformation) => transformation.key),
    ];
    // For use in the next request handler
    res.locals.shortcuts = [...constants_1.SYSTEM_ASSET_WHITELIST, assetSettings.asset_shortcuts];
    res.locals.transformation = transformation;
    if (Object.keys(transformation).length === 0) {
        return next();
    }
    if (assetSettings.asset_generation === 'all') {
        if (transformation.key && allKeys.includes(transformation.key) === false)
            throw new exceptions_1.InvalidQueryException(`Key "${transformation.key}" isn't configured.`);
        return next();
    }
    else if (assetSettings.asset_generation === 'shortcut') {
        if (allKeys.includes(transformation.key))
            return next();
        throw new exceptions_1.InvalidQueryException(`Only configured shortcuts can be used in asset generation.`);
    }
    else {
        if (transformation.key && systemKeys.includes(transformation.key))
            return next();
        throw new exceptions_1.InvalidQueryException(`Dynamic asset generation has been disabled for this project.`);
    }
})), 
// Return file
express_async_handler_1.default((req, res) => __awaiter(void 0, void 0, void 0, function* () {
    const transformation = res.locals.transformation.key
        ? res.locals.shortcuts.find((transformation) => transformation.key === res.locals.transformation.key)
        : res.locals.transformation;
    const { stream, file } = yield AssetsService.getAsset(req.params.pk, transformation);
    res.setHeader('Content-Disposition', 'attachment; filename=' + file.filename_download);
    res.setHeader('Content-Type', file.type);
    stream.pipe(res);
})));
exports.default = router;
