"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.modifyExe = modifyExe;
const path_1 = require("path");
const logger_1 = require("../../utils/logger");
const fs_1 = require("fs");
const config_service_1 = require("../config/config.service");
const path_2 = require("../../utils/path");
const child_process_1 = require("child_process");
const find_package_dir_1 = require("../../utils/find.package.dir");
const version_1 = require("../../utils/version");
const error_handler_1 = require("../../utils/error.handler");
const logger = logger_1.Logger.getInstance("modifications.windows.helper");
async function modifyExe() {
    logger.info("Modifying Windows executable...");
    restoreOriginalUnsignedExeIfNeeded();
    const defaultIOCDPath = (0, path_1.join)(path_2.PathUtils.getComponentDir("iocd"), "io-connect-desktop.exe");
    const options = config_service_1.ConfigManager.config;
    const newExePath = renameExe(defaultIOCDPath, options.win.exe.exeName);
    if (isFileLocked(newExePath)) {
        throw new error_handler_1.CLIError(`Cannot modify executable because it is locked: ${newExePath}.`, {
            suggestions: [
                "Please close any running instances of the application and try again.",
            ],
        });
    }
    else {
        logger.debug("Executable is not locked, proceeding with modifications.");
    }
    await changeIconAndMetadata(newExePath, options);
    logger.info("Modification complete successfully!");
}
function restoreOriginalUnsignedExeIfNeeded() {
    // we store the original unsigned exe before signing, because rcedit can be done on unsigned exe only (see installer/windows.helper.ts for store logic).
    // at this point we are restoring it so we can do rcedit again if needed.
    logger.debug("Will check if original unsigned exe exists in _temp...");
    const tempDir = path_2.PathUtils.getComponentDir("_temp");
    const exeBaseName = (0, path_1.basename)(path_2.PathUtils.getIOCDExePath());
    const tempPath = (0, path_1.join)(tempDir, exeBaseName);
    if ((0, fs_1.existsSync)(tempPath)) {
        logger.debug("Restoring exe from _temp directory...");
        (0, fs_1.copyFileSync)(tempPath, path_2.PathUtils.getIOCDExePath());
        logger.debug("Restored exe from _temp directory.");
    }
    else {
        logger.debug("No original unsigned exe found in _temp, skipping restore.");
    }
}
/** rename io-connect-desktop.exe in the path to newName.exe; don to use regex */
function renameExe(path, newName) {
    logger.debug(`Renaming executable in path: ${path} to ${newName}.exe`);
    const dir = (0, path_1.dirname)(path);
    const oldPath = (0, path_1.join)(dir, "io-connect-desktop.exe");
    const newPath = (0, path_1.join)(dir, `${newName}`);
    const oldExists = (0, fs_1.existsSync)(oldPath);
    const newExists = (0, fs_1.existsSync)(newPath);
    if (newExists) {
        logger.debug(`File with new name already exists, skipping rename: ${newPath}`);
        return newPath;
    }
    if (oldExists) {
        (0, fs_1.renameSync)(oldPath, newPath);
        logger.debug(`Renamed: ${oldPath} -> ${newPath}`);
    }
    else {
        throw new Error(`File not found: ${oldPath} and new file does not exist: ${newPath}`);
    }
    return newPath;
}
async function changeIconAndMetadata(exePath, options) {
    return new Promise((resolve, reject) => {
        logger.debug(`Updating icon and metadata for executable: ${exePath}`);
        const rceditPath = (0, path_1.join)((0, find_package_dir_1.findPackageRoot)(), "tools", "rcedit-x64.exe");
        const args = [
            exePath,
            "--set-icon",
            options.win.exe.exeIconPath,
            "--set-version-string",
            "CompanyName",
            options.company,
            "--set-version-string",
            "FileDescription",
            options.productDescription,
            "--set-version-string",
            "ProductName",
            options.productName,
            "--set-file-version",
            (0, version_1.makeVersionFourDigitsIfNeeded)(options.version),
            "--set-product-version",
            options.version,
        ];
        const callback = (error, stdout, stderr) => {
            if (error) {
                logger.error("rcedit error:", error);
                return reject(error);
            }
            if (stderr) {
                logger.error("rcedit stderr:", stderr);
            }
            logger.debug("rcedit output:", stdout);
            resolve();
        };
        logger.debug(`Executing rcedit with args: ${args.join(" ")}`);
        if (process.platform === "linux") {
            (0, child_process_1.execFile)("wine64", [rceditPath, ...args], callback);
        }
        else {
            (0, child_process_1.execFile)(rceditPath, args, callback);
        }
    });
}
function isFileLocked(path) {
    try {
        logger.debug(`Checking if file is locked: ${path}`);
        const fd = (0, fs_1.openSync)(path, "r+"); // request read/write exclusive access
        (0, fs_1.closeSync)(fd);
        logger.debug(`File is not locked: ${path}`);
        return false; // success -> not locked
    }
    catch (err) {
        logger.debug(`Error while checking if file is locked: ${path}`, err);
        // Common Windows lock errors:
        if (["EPERM", "EBUSY", "EACCES"].includes(err.code)) {
            return true;
        }
        return false;
    }
}
//# sourceMappingURL=windows.helper.js.map