"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.onMoveToObjectStorageFailure = exports.processMoveToObjectStorage = void 0;
const tslib_1 = require("tslib");
const fs_extra_1 = require("fs-extra");
const path_1 = require("path");
const logger_1 = require("../../../helpers/logger");
const webtorrent_1 = require("../../../helpers/webtorrent");
const constants_1 = require("../../../initializers/constants");
const object_storage_1 = require("../../object-storage");
const paths_1 = require("../../paths");
const video_path_manager_1 = require("../../video-path-manager");
const video_state_1 = require("../../video-state");
const video_1 = require("../../../models/video/video");
const video_job_info_1 = require("../../../models/video/video-job-info");
const lTagsBase = (0, logger_1.loggerTagsFactory)('move-object-storage');
function processMoveToObjectStorage(job) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const payload = job.data;
        logger_1.logger.info('Moving video %s in job %s.', payload.videoUUID, job.id);
        const video = yield video_1.VideoModel.loadWithFiles(payload.videoUUID);
        if (!video) {
            logger_1.logger.info('Can\'t process job %d, video does not exist.', job.id, lTagsBase(payload.videoUUID));
            return undefined;
        }
        const lTags = lTagsBase(video.uuid, video.url);
        const fileMutexReleaser = yield video_path_manager_1.VideoPathManager.Instance.lockFiles(video.uuid);
        try {
            if (video.VideoFiles) {
                logger_1.logger.debug('Moving %d webtorrent files for video %s.', video.VideoFiles.length, video.uuid, lTags);
                yield moveWebTorrentFiles(video);
            }
            if (video.VideoStreamingPlaylists) {
                logger_1.logger.debug('Moving HLS playlist of %s.', video.uuid);
                yield moveHLSFiles(video);
            }
            const pendingMove = yield video_job_info_1.VideoJobInfoModel.decrease(video.uuid, 'pendingMove');
            if (pendingMove === 0) {
                logger_1.logger.info('Running cleanup after moving files to object storage (video %s in job %s)', video.uuid, job.id, lTags);
                yield doAfterLastJob({ video, previousVideoState: payload.previousVideoState, isNewVideo: payload.isNewVideo });
            }
        }
        catch (err) {
            yield onMoveToObjectStorageFailure(job, err);
            throw err;
        }
        finally {
            fileMutexReleaser();
        }
        return payload.videoUUID;
    });
}
exports.processMoveToObjectStorage = processMoveToObjectStorage;
function onMoveToObjectStorageFailure(job, err) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const payload = job.data;
        const video = yield video_1.VideoModel.loadWithFiles(payload.videoUUID);
        if (!video)
            return;
        logger_1.logger.error('Cannot move video %s to object storage.', video.url, Object.assign({ err }, lTagsBase(video.uuid, video.url)));
        yield (0, video_state_1.moveToFailedMoveToObjectStorageState)(video);
        yield video_job_info_1.VideoJobInfoModel.abortAllTasks(video.uuid, 'pendingMove');
    });
}
exports.onMoveToObjectStorageFailure = onMoveToObjectStorageFailure;
function moveWebTorrentFiles(video) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        for (const file of video.VideoFiles) {
            if (file.storage !== 0)
                continue;
            const fileUrl = yield (0, object_storage_1.storeWebTorrentFile)(video, file);
            const oldPath = video_path_manager_1.VideoPathManager.Instance.getFSVideoFileOutputPath(video, file);
            yield onFileMoved({ videoOrPlaylist: video, file, fileUrl, oldPath });
        }
    });
}
function moveHLSFiles(video) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        for (const playlist of video.VideoStreamingPlaylists) {
            const playlistWithVideo = playlist.withVideo(video);
            for (const file of playlist.VideoFiles) {
                if (file.storage !== 0)
                    continue;
                const playlistFilename = (0, paths_1.getHlsResolutionPlaylistFilename)(file.filename);
                yield (0, object_storage_1.storeHLSFileFromFilename)(playlistWithVideo, playlistFilename);
                const fileUrl = yield (0, object_storage_1.storeHLSFileFromFilename)(playlistWithVideo, file.filename);
                const oldPath = (0, path_1.join)((0, paths_1.getHLSDirectory)(video), file.filename);
                yield onFileMoved({ videoOrPlaylist: Object.assign(playlist, { Video: video }), file, fileUrl, oldPath });
            }
        }
    });
}
function doAfterLastJob(options) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const { video, previousVideoState, isNewVideo } = options;
        for (const playlist of video.VideoStreamingPlaylists) {
            if (playlist.storage === 1)
                continue;
            const playlistWithVideo = playlist.withVideo(video);
            playlist.playlistUrl = yield (0, object_storage_1.storeHLSFileFromFilename)(playlistWithVideo, playlist.playlistFilename);
            playlist.segmentsSha256Url = yield (0, object_storage_1.storeHLSFileFromFilename)(playlistWithVideo, playlist.segmentsSha256Filename);
            playlist.storage = 1;
            playlist.assignP2PMediaLoaderInfoHashes(video, playlist.VideoFiles);
            playlist.p2pMediaLoaderPeerVersion = constants_1.P2P_MEDIA_LOADER_PEER_VERSION;
            yield playlist.save();
        }
        if (video.VideoStreamingPlaylists) {
            yield (0, fs_extra_1.remove)((0, paths_1.getHLSDirectory)(video));
        }
        yield (0, video_state_1.moveToNextState)({ video, previousVideoState, isNewVideo });
    });
}
function onFileMoved(options) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const { videoOrPlaylist, file, fileUrl, oldPath } = options;
        file.fileUrl = fileUrl;
        file.storage = 1;
        yield (0, webtorrent_1.updateTorrentMetadata)(videoOrPlaylist, file);
        yield file.save();
        logger_1.logger.debug('Removing %s because it\'s now on object storage', oldPath);
        yield (0, fs_extra_1.remove)(oldPath);
    });
}
//# sourceMappingURL=move-to-object-storage.js.map