"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.VideoPathManager = void 0;
const tslib_1 = require("tslib");
const async_mutex_1 = require("async-mutex");
const fs_extra_1 = require("fs-extra");
const path_1 = require("path");
const logger_1 = require("../helpers/logger");
const video_1 = require("../helpers/video");
const config_1 = require("../initializers/config");
const constants_1 = require("../initializers/constants");
const extra_utils_1 = require("../../shared/extra-utils");
const object_storage_1 = require("./object-storage");
const paths_1 = require("./paths");
const video_privacy_1 = require("./video-privacy");
const lTags = (0, logger_1.loggerTagsFactory)('video-path-manager');
class VideoPathManager {
    constructor() {
        this.videoFileMutexStore = new Map();
    }
    getFSHLSOutputPath(video, filename) {
        const base = (0, paths_1.getHLSDirectory)(video);
        if (!filename)
            return base;
        return (0, path_1.join)(base, filename);
    }
    getFSRedundancyVideoFilePath(videoOrPlaylist, videoFile) {
        if (videoFile.isHLS()) {
            const video = (0, video_1.extractVideo)(videoOrPlaylist);
            return (0, path_1.join)((0, paths_1.getHLSRedundancyDirectory)(video), videoFile.filename);
        }
        return (0, path_1.join)(config_1.CONFIG.STORAGE.REDUNDANCY_DIR, videoFile.filename);
    }
    getFSVideoFileOutputPath(videoOrPlaylist, videoFile) {
        const video = (0, video_1.extractVideo)(videoOrPlaylist);
        if (videoFile.isHLS()) {
            return (0, path_1.join)((0, paths_1.getHLSDirectory)(video), videoFile.filename);
        }
        if ((0, video_privacy_1.isVideoInPrivateDirectory)(video.privacy)) {
            return (0, path_1.join)(constants_1.DIRECTORIES.VIDEOS.PRIVATE, videoFile.filename);
        }
        return (0, path_1.join)(constants_1.DIRECTORIES.VIDEOS.PUBLIC, videoFile.filename);
    }
    makeAvailableVideoFile(videoFile, cb) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            if (videoFile.storage === 0) {
                return this.makeAvailableFactory(() => this.getFSVideoFileOutputPath(videoFile.getVideoOrStreamingPlaylist(), videoFile), false, cb);
            }
            const destination = this.buildTMPDestination(videoFile.filename);
            if (videoFile.isHLS()) {
                const playlist = videoFile.VideoStreamingPlaylist;
                return this.makeAvailableFactory(() => (0, object_storage_1.makeHLSFileAvailable)(playlist, videoFile.filename, destination), true, cb);
            }
            return this.makeAvailableFactory(() => (0, object_storage_1.makeWebTorrentFileAvailable)(videoFile.filename, destination), true, cb);
        });
    }
    makeAvailableResolutionPlaylistFile(videoFile, cb) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const filename = (0, paths_1.getHlsResolutionPlaylistFilename)(videoFile.filename);
            if (videoFile.storage === 0) {
                return this.makeAvailableFactory(() => (0, path_1.join)((0, paths_1.getHLSDirectory)(videoFile.getVideo()), filename), false, cb);
            }
            const playlist = videoFile.VideoStreamingPlaylist;
            return this.makeAvailableFactory(() => (0, object_storage_1.makeHLSFileAvailable)(playlist, filename, this.buildTMPDestination(filename)), true, cb);
        });
    }
    makeAvailablePlaylistFile(playlist, filename, cb) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            if (playlist.storage === 0) {
                return this.makeAvailableFactory(() => (0, path_1.join)((0, paths_1.getHLSDirectory)(playlist.Video), filename), false, cb);
            }
            return this.makeAvailableFactory(() => (0, object_storage_1.makeHLSFileAvailable)(playlist, filename, this.buildTMPDestination(filename)), true, cb);
        });
    }
    lockFiles(videoUUID) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            if (!this.videoFileMutexStore.has(videoUUID)) {
                this.videoFileMutexStore.set(videoUUID, new async_mutex_1.Mutex());
            }
            const mutex = this.videoFileMutexStore.get(videoUUID);
            const releaser = yield mutex.acquire();
            logger_1.logger.debug('Locked files of %s.', videoUUID, lTags(videoUUID));
            return releaser;
        });
    }
    unlockFiles(videoUUID) {
        const mutex = this.videoFileMutexStore.get(videoUUID);
        mutex.release();
        logger_1.logger.debug('Released lockfiles of %s.', videoUUID, lTags(videoUUID));
    }
    makeAvailableFactory(method, clean, cb) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            let result;
            const destination = yield method();
            try {
                result = yield cb(destination);
            }
            catch (err) {
                if (destination && clean)
                    yield (0, fs_extra_1.remove)(destination);
                throw err;
            }
            if (clean)
                yield (0, fs_extra_1.remove)(destination);
            return result;
        });
    }
    buildTMPDestination(filename) {
        return (0, path_1.join)(config_1.CONFIG.STORAGE.TMP_DIR, (0, extra_utils_1.buildUUID)() + (0, path_1.extname)(filename));
    }
    static get Instance() {
        return this.instance || (this.instance = new this());
    }
}
exports.VideoPathManager = VideoPathManager;
//# sourceMappingURL=video-path-manager.js.map