"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getImageSize = exports.processImage = exports.generateImageFromVideoFile = exports.generateImageFilename = void 0;
const tslib_1 = require("tslib");
const fs_extra_1 = require("fs-extra");
const jimp_1 = require("jimp");
const path_1 = require("path");
const core_utils_1 = require("../../shared/core-utils");
const extra_utils_1 = require("../../shared/extra-utils");
const ffmpeg_images_1 = require("./ffmpeg/ffmpeg-images");
const logger_1 = require("./logger");
const lTags = (0, logger_1.loggerTagsFactory)('image-utils');
function generateImageFilename(extension = '.jpg') {
    return (0, extra_utils_1.buildUUID)() + extension;
}
exports.generateImageFilename = generateImageFilename;
function processImage(options) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const { path, destination, newSize, keepOriginal = false } = options;
        const extension = (0, core_utils_1.getLowercaseExtension)(path);
        if (path === destination) {
            throw new Error('Jimp/FFmpeg needs an input path different that the output path.');
        }
        logger_1.logger.debug('Processing image %s to %s.', path, destination);
        if (extension === '.gif') {
            yield (0, ffmpeg_images_1.processGIF)(path, destination, newSize);
        }
        else {
            yield jimpProcessor(path, destination, newSize, extension);
        }
        if (keepOriginal !== true)
            yield (0, fs_extra_1.remove)(path);
    });
}
exports.processImage = processImage;
function generateImageFromVideoFile(options) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const { fromPath, folder, imageName, size } = options;
        const pendingImageName = 'pending-' + imageName;
        const pendingImagePath = (0, path_1.join)(folder, pendingImageName);
        try {
            yield (0, ffmpeg_images_1.generateThumbnailFromVideo)(fromPath, folder, imageName);
            const destination = (0, path_1.join)(folder, imageName);
            yield processImage({ path: pendingImagePath, destination, newSize: size });
        }
        catch (err) {
            logger_1.logger.error('Cannot generate image from video %s.', fromPath, Object.assign({ err }, lTags()));
            try {
                yield (0, fs_extra_1.remove)(pendingImagePath);
            }
            catch (err) {
                logger_1.logger.debug('Cannot remove pending image path after generation error.', Object.assign({ err }, lTags()));
            }
        }
    });
}
exports.generateImageFromVideoFile = generateImageFromVideoFile;
function getImageSize(path) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const inputBuffer = yield (0, fs_extra_1.readFile)(path);
        const image = yield (0, jimp_1.read)(inputBuffer);
        return {
            width: image.getWidth(),
            height: image.getHeight()
        };
    });
}
exports.getImageSize = getImageSize;
function jimpProcessor(path, destination, newSize, inputExt) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        let sourceImage;
        const inputBuffer = yield (0, fs_extra_1.readFile)(path);
        try {
            sourceImage = yield (0, jimp_1.read)(inputBuffer);
        }
        catch (err) {
            logger_1.logger.debug('Cannot read %s with jimp. Try to convert the image using ffmpeg first.', path, { err });
            const newName = path + '.jpg';
            yield (0, ffmpeg_images_1.convertWebPToJPG)(path, newName);
            yield (0, fs_extra_1.rename)(newName, path);
            sourceImage = yield (0, jimp_1.read)(path);
        }
        yield (0, fs_extra_1.remove)(destination);
        const outputExt = (0, core_utils_1.getLowercaseExtension)(destination);
        if (skipProcessing({ sourceImage, newSize, imageBytes: inputBuffer.byteLength, inputExt, outputExt })) {
            return (0, fs_extra_1.copy)(path, destination);
        }
        yield autoResize({ sourceImage, newSize, destination });
    });
}
function autoResize(options) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const { sourceImage, newSize, destination } = options;
        const sourceIsPortrait = sourceImage.getWidth() < sourceImage.getHeight();
        const destIsPortraitOrSquare = newSize.width <= newSize.height;
        removeExif(sourceImage);
        if (sourceIsPortrait && !destIsPortraitOrSquare) {
            const baseImage = sourceImage.cloneQuiet().cover(newSize.width, newSize.height)
                .color([{ apply: 'shade', params: [50] }]);
            const topImage = sourceImage.cloneQuiet().contain(newSize.width, newSize.height);
            return write(baseImage.blit(topImage, 0, 0), destination);
        }
        return write(sourceImage.cover(newSize.width, newSize.height), destination);
    });
}
function write(image, destination) {
    return image.quality(80).writeAsync(destination);
}
function skipProcessing(options) {
    const { sourceImage, newSize, imageBytes, inputExt, outputExt } = options;
    const { width, height } = newSize;
    if (hasExif(sourceImage))
        return false;
    if (sourceImage.getWidth() > width || sourceImage.getHeight() > height)
        return false;
    if (inputExt !== outputExt)
        return false;
    const kB = 1000;
    if (height >= 1000)
        return imageBytes <= 200 * kB;
    if (height >= 500)
        return imageBytes <= 100 * kB;
    return imageBytes <= 15 * kB;
}
function hasExif(image) {
    return !!image.bitmap.exifBuffer;
}
function removeExif(image) {
    image.bitmap.exifBuffer = null;
}
//# sourceMappingURL=image-utils.js.map