"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Win32Installer = void 0;
const child_process_1 = require("child_process");
const os_1 = require("os");
const path_1 = require("path");
const axios_1 = require("axios");
const fs_extra_1 = require("fs-extra");
const base_platform_1 = require("../base-platform");
class Win32Installer extends base_platform_1.BasePlatform {
    async install() {
        this.checkIsAdmin();
        await this.hbService.portCheck();
        await this.hbService.storagePathCheck();
        await this.hbService.configCheck();
        const nssmPath = await this.downloadNssm();
        const installCmd = `"${nssmPath}" install ${this.hbService.serviceName} ` +
            `"${process.execPath}" "\""${this.hbService.selfPath}"\"" run -I -U "\""${this.hbService.storagePath}"\""`;
        const setUserDirCmd = `"${nssmPath}" set ${this.hbService.serviceName} AppEnvironmentExtra ":UIX_STORAGE_PATH=${this.hbService.storagePath}"`;
        try {
            (0, child_process_1.execSync)(installCmd);
            (0, child_process_1.execSync)(setUserDirCmd);
            await this.configureFirewall();
            await this.start();
            await this.hbService.printPostInstallInstructions();
        }
        catch (e) {
            console.error(e.toString());
            this.hbService.logger('ERROR: Failed Operation', 'fail');
        }
    }
    async uninstall() {
        this.checkIsAdmin();
        await this.stop();
        try {
            (0, child_process_1.execSync)(`sc delete ${this.hbService.serviceName}`);
            this.hbService.logger(`Removed ${this.hbService.serviceName} Service`, 'succeed');
        }
        catch (e) {
            console.error(e.toString());
            this.hbService.logger('ERROR: Failed Operation', 'fail');
        }
    }
    async start() {
        this.checkIsAdmin();
        try {
            this.hbService.logger(`Starting ${this.hbService.serviceName} Service...`);
            (0, child_process_1.execSync)(`sc start ${this.hbService.serviceName}`);
            this.hbService.logger(`${this.hbService.serviceName} Started`, 'succeed');
        }
        catch (e) {
            this.hbService.logger(`Failed to start ${this.hbService.serviceName}`, 'fail');
        }
    }
    async stop() {
        this.checkIsAdmin();
        try {
            this.hbService.logger(`Stopping ${this.hbService.serviceName} Service...`);
            (0, child_process_1.execSync)(`sc stop ${this.hbService.serviceName}`);
            this.hbService.logger(`${this.hbService.serviceName} Stopped`, 'succeed');
        }
        catch (e) {
            this.hbService.logger(`Failed to stop ${this.hbService.serviceName}`, 'fail');
        }
    }
    async restart() {
        this.checkIsAdmin();
        await this.stop();
        setTimeout(async () => {
            await this.start();
        }, 4000);
    }
    async rebuild(all = false) {
        this.checkIsAdmin();
        try {
            (0, child_process_1.execSync)('npm rebuild --unsafe-perm', {
                cwd: process.env.UIX_BASE_PATH,
                stdio: 'inherit',
            });
            this.hbService.logger(`Rebuilt modules in ${process.env.UIX_BASE_PATH} for Node.js ${process.version}.`, 'succeed');
        }
        catch (e) {
            console.error(e.toString());
            this.hbService.logger('ERROR: Failed Operation', 'fail');
        }
    }
    async updateNodejs(job) {
        this.hbService.logger('ERROR: This command is not supported on Windows.', 'fail');
        this.hbService.logger(`Please download Node.js v${job.target} from https://nodejs.org/en/download/ and install manually.`, 'fail');
    }
    checkIsAdmin() {
        try {
            (0, child_process_1.execSync)('fsutil dirty query %systemdrive% >nul');
        }
        catch (e) {
            this.hbService.logger('ERROR: This command must be run as an Administrator', 'fail');
            this.hbService.logger('Node.js command prompt shortcut -> Right Click -> Run as administrator', 'fail');
            process.exit(1);
        }
    }
    async downloadNssm() {
        const downloadUrl = `https://github.com/homebridge/nssm/releases/download/2.24-101-g897c7ad/nssm_${(0, os_1.arch)()}.exe`;
        const nssmPath = (0, path_1.resolve)(this.hbService.storagePath, 'nssm.exe');
        if (await (0, fs_extra_1.pathExists)(nssmPath)) {
            return nssmPath;
        }
        const nssmFile = (0, fs_extra_1.createWriteStream)(nssmPath);
        this.hbService.logger(`Downloading NSSM from ${downloadUrl}`);
        return new Promise((res, rej) => {
            (0, axios_1.default)({
                method: 'GET',
                url: downloadUrl,
                responseType: 'stream',
            }).then((response) => {
                response.data.pipe(nssmFile)
                    .on('finish', () => {
                    return res(nssmPath);
                })
                    .on('error', (err) => {
                    return rej(err);
                });
            }).catch(async (e) => {
                nssmFile.close();
                await (0, fs_extra_1.remove)(nssmPath);
                this.hbService.logger(`Failed to download nssm: ${e.message}`, 'fail');
                process.exit(0);
            });
        });
    }
    async configureFirewall() {
        const cleanFirewallCmd = 'netsh advfirewall firewall Delete rule name="Homebridge"';
        const openFirewallCmd = `netsh advfirewall firewall add rule name="Homebridge" dir=in action=allow program="${process.execPath}"`;
        try {
            (0, child_process_1.execSync)(cleanFirewallCmd);
        }
        catch (e) {
        }
        try {
            (0, child_process_1.execSync)(openFirewallCmd);
        }
        catch (e) {
            this.hbService.logger('Failed to configure firewall rule for Homebridge.', 'warn');
            this.hbService.logger(e);
        }
    }
}
exports.Win32Installer = Win32Installer;
//# sourceMappingURL=win32.js.map