"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AssetsGenerationService = void 0;
const JimpModule = require("jimp");
const Color = require("color");
const decorators_1 = require("../../common/decorators");
const constants_1 = require("../../constants");
const _ = require("lodash");
const yok_1 = require("../../common/yok");
const os_1 = require("os");
class AssetsGenerationService {
    get propertiesToEnumerate() {
        return {
            icon: ["icons"],
            splash: ["splashBackgrounds", "splashCenterImages", "splashImages"],
        };
    }
    constructor($logger, $projectDataService, $fs, $options) {
        this.$logger = $logger;
        this.$projectDataService = $projectDataService;
        this.$fs = $fs;
        this.$options = $options;
    }
    async generateIcons(resourceGenerationData) {
        if (this.$options.hostProjectPath) {
            return;
        }
        this.$logger.info("Generating icons ...");
        await this.generateImagesForDefinitions(resourceGenerationData, this.propertiesToEnumerate.icon);
        this.$logger.info("Icons generation completed.");
    }
    async generateSplashScreens(splashesGenerationData) {
        this.$logger.info("Generating splash screens ...");
        await this.generateImagesForDefinitions(splashesGenerationData, this.propertiesToEnumerate.splash);
        this.$logger.info("Splash screens generation completed.");
    }
    async generateImagesForDefinitions(generationData, propertiesToEnumerate) {
        var _a, _b, _c, _d, _e, _f;
        const background = generationData.background || "white";
        const assetsStructure = await this.$projectDataService.getAssetsStructure(generationData);
        const assetItems = _(assetsStructure)
            .filter((assetGroup, platform) => !generationData.platform ||
            platform.toLowerCase() === generationData.platform.toLowerCase())
            .map((assetGroup) => _.filter(assetGroup, (assetSubGroup, imageTypeKey) => assetSubGroup && propertiesToEnumerate.indexOf(imageTypeKey) !== -1))
            .flatten()
            .map((assetSubGroup) => assetSubGroup.images)
            .flatten()
            .filter((assetItem) => !!assetItem.filename)
            .value();
        for (const assetItem of assetItems) {
            if (assetItem.operation === "delete") {
                if (this.$fs.exists(assetItem.path)) {
                    this.$fs.deleteFile(assetItem.path);
                }
                continue;
            }
            if (assetItem.operation === "writeXMLColor") {
                const colorName = (_a = assetItem.data) === null || _a === void 0 ? void 0 : _a.colorName;
                if (!colorName) {
                    continue;
                }
                try {
                    const color = (_e = (_c = generationData[(_b = assetItem.data) === null || _b === void 0 ? void 0 : _b.fromKey]) !== null && _c !== void 0 ? _c : (_d = assetItem.data) === null || _d === void 0 ? void 0 : _d.default) !== null && _e !== void 0 ? _e : "white";
                    const colorHEX = JimpModule.cssColorToHex(color);
                    const hex = (_f = colorHEX === null || colorHEX === void 0 ? void 0 : colorHEX.toString(16).substring(0, 6)) !== null && _f !== void 0 ? _f : "FFFFFF";
                    this.$fs.writeFile(assetItem.path, [
                        `<?xml version="1.0" encoding="utf-8"?>`,
                        `<resources>`,
                        `    <color name="${colorName}">#${hex.toUpperCase()}</color>`,
                        `</resources>`,
                    ].join(os_1.EOL));
                }
                catch (err) {
                    this.$logger.info(`Failed to write provided color to ${assetItem.path} -> ${colorName}. See --log trace for more info.`);
                    this.$logger.trace(err);
                }
                continue;
            }
            const operation = assetItem.resizeOperation || "resize";
            let tempScale = null;
            if (assetItem.scale) {
                if (_.isNumber(assetItem.scale)) {
                    tempScale = assetItem.scale;
                }
                else {
                    const splittedElements = `${assetItem.scale}`.split(constants_1.AssetConstants.sizeDelimiter);
                    tempScale =
                        splittedElements &&
                            splittedElements.length &&
                            splittedElements[0] &&
                            +splittedElements[0];
                }
            }
            const scale = tempScale || constants_1.AssetConstants.defaultScale;
            const outputPath = assetItem.path;
            const width = assetItem.width * scale;
            const height = assetItem.height * scale;
            if (!width || !height) {
                this.$logger.warn(`Image ${assetItem.filename} is skipped as its width and height are invalid.`);
                continue;
            }
            let image;
            switch (operation) {
                case "overlayWith":
                    const overlayImageScale = assetItem.overlayImageScale ||
                        constants_1.AssetConstants.defaultOverlayImageScale;
                    const imageResize = Math.round(Math.min(width, height) * overlayImageScale);
                    image = await this.resize(generationData.imagePath, imageResize, imageResize);
                    image = this.generateImage(background, width, height, image);
                    break;
                case "blank":
                    image = this.generateImage(background, width, height);
                    break;
                case "resize":
                    image = await this.resize(generationData.imagePath, width, height);
                    break;
                case "outerScale":
                    image = await this.resize(generationData.imagePath, assetItem.width, assetItem.height);
                    image = this.generateImage("#00000000", width, height, image);
                    break;
                default:
                    throw new Error(`Invalid image generation operation: ${operation}`);
            }
            if (assetItem.rgba === false) {
                image = this.generateImage("#FFFFFF", image.width, image.height, image);
            }
            if (this.isAssetFilePath(outputPath)) {
                image.write(outputPath);
            }
            else {
                this.$logger.warn(`Incorrect destination path ${outputPath} for image ${assetItem.filename}`);
            }
        }
    }
    async resize(imagePath, width, height) {
        const image = await JimpModule.Jimp.read(imagePath);
        return image.scaleToFit({
            w: width,
            h: height,
        });
    }
    generateImage(background, width, height, overlayImage) {
        const backgroundColor = this.getRgbaNumber(background);
        let image = new JimpModule.Jimp({
            width,
            height,
            color: backgroundColor,
        });
        if (overlayImage) {
            const centeredWidth = (width - overlayImage.width) / 2;
            const centeredHeight = (height - overlayImage.height) / 2;
            image = image.composite(overlayImage, centeredWidth, centeredHeight);
        }
        return image;
    }
    getRgbaNumber(colorString) {
        const color = new Color(colorString);
        const colorRgb = color.rgb();
        const alpha = Math.round(colorRgb.alpha() * 255);
        return JimpModule.rgbaToInt(colorRgb.red(), colorRgb.green(), colorRgb.blue(), alpha);
    }
    isAssetFilePath(path) {
        if (!path) {
            return false;
        }
        const index = path.lastIndexOf(".");
        return index > -1 && index < path.length - 1;
    }
}
exports.AssetsGenerationService = AssetsGenerationService;
__decorate([
    (0, decorators_1.exported)("assetsGenerationService")
], AssetsGenerationService.prototype, "generateIcons", null);
__decorate([
    (0, decorators_1.exported)("assetsGenerationService")
], AssetsGenerationService.prototype, "generateSplashScreens", null);
yok_1.injector.register("assetsGenerationService", AssetsGenerationService);
