"use strict";
/**
 * penguins-eggs
 * krill modules: krill-sequence.ts
 * author: Piero Proietti
 * email: piero.proietti@gmail.com
 * license: MIT
 * https://stackoverflow.com/questions/23876782/how-do-i-split-a-typescript-class-into-multiple-files
 */
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const settings_1 = tslib_1.__importDefault(require("../classes/settings"));
const react_1 = tslib_1.__importDefault(require("react"));
const ink_1 = require("ink");
const install_1 = tslib_1.__importDefault(require("../components/install"));
const finished_1 = tslib_1.__importDefault(require("../components/finished"));
const fs_1 = tslib_1.__importDefault(require("fs"));
const js_yaml_1 = tslib_1.__importDefault(require("js-yaml"));
const utils_1 = tslib_1.__importDefault(require("../classes/utils"));
const cli_autologin_1 = tslib_1.__importDefault(require("../lib/cli-autologin"));
const pacman_1 = tslib_1.__importDefault(require("../classes/pacman"));
const installer_1 = require("../classes/incubation/installer");
const xdg_1 = tslib_1.__importDefault(require("../classes/xdg"));
const distro_1 = tslib_1.__importDefault(require("../classes/distro"));
const utils_2 = require("../lib/utils");
// import krill modules
const partition_1 = tslib_1.__importDefault(require("./modules/partition"));
const mount_fs_1 = require("./modules/mount-fs");
const mount_vfs_1 = require("./modules/mount-vfs");
const unpackfs_1 = tslib_1.__importDefault(require("./modules/unpackfs"));
const machine_id_1 = tslib_1.__importDefault(require("./modules/machine-id"));
const fstab_1 = tslib_1.__importDefault(require("./modules/fstab"));
const locale_1 = tslib_1.__importDefault(require("./modules/locale"));
const m_keyboard_1 = tslib_1.__importDefault(require("./modules/m-keyboard"));
const locale_cfg_1 = tslib_1.__importDefault(require("./modules/locale-cfg"));
// users
const add_user_1 = tslib_1.__importDefault(require("./modules/add-user"));
const change_password_1 = tslib_1.__importDefault(require("./modules/change-password"));
// displaymanager: autologin
const network_cfg_1 = tslib_1.__importDefault(require("./modules/network-cfg"));
// hwclock:
// services-systemd:
// bootloader-config
const bootloader_config_1 = tslib_1.__importDefault(require("./modules/bootloader-config"));
const bootloader_config_arch_1 = tslib_1.__importDefault(require("./modules/bootloader-config-arch"));
const bootloader_config_debian_1 = tslib_1.__importDefault(require("./modules/bootloader-config-debian"));
const grubcfg_1 = tslib_1.__importDefault(require("./modules/grubcfg"));
const bootloader_1 = tslib_1.__importDefault(require("./modules/bootloader"));
const packages_1 = tslib_1.__importDefault(require("./modules/packages"));
const remove_installer_link_1 = tslib_1.__importDefault(require("./modules/remove-installer-link"));
// luksbootkeyfile:
// plymouthcfg;
const initramfs_cfg_1 = tslib_1.__importDefault(require("./modules/initramfs-cfg"));
const initramfs_1 = tslib_1.__importDefault(require("./modules/initramfs"));
const del_live_user_1 = tslib_1.__importDefault(require("./modules/del-live-user"));
// umount already imported
// to order in same wat
const m_timezone_1 = tslib_1.__importDefault(require("./modules/m-timezone"));
const umount_1 = tslib_1.__importDefault(require("./modules/umount"));
const mkfs_1 = tslib_1.__importDefault(require("./modules/mkfs"));
const hostname_1 = tslib_1.__importDefault(require("./modules/hostname"));
const cfs_1 = tslib_1.__importDefault(require("../classes/cfs"));
/**
 * hatching: installazione o cova!!!
 */
class Sequence {
    /**
     * constructor
     */
    constructor(location, keyboard, partitions, users, network) {
        this.partition = partition_1.default;
        // mount
        this.mountFs = mount_fs_1.mountFs;
        this.mountVfs = mount_vfs_1.mountVfs;
        //
        this.unpackfs = unpackfs_1.default;
        this.machineId = machine_id_1.default;
        this.fstab = fstab_1.default;
        this.locale = locale_1.default;
        this.keyboard = m_keyboard_1.default;
        this.localeCfg = locale_cfg_1.default;
        // users
        this.addUser = add_user_1.default;
        this.changePassword = change_password_1.default;
        // displaumanager: autologin
        this.networkCfg = network_cfg_1.default;
        // hwclock:
        // services-systemd:
        // bootloader-config
        this.bootloaderConfig = bootloader_config_1.default;
        this.bootloaderConfigArch = bootloader_config_arch_1.default;
        this.bootloaderConfigDebian = bootloader_config_debian_1.default;
        //
        this.grubcfg = grubcfg_1.default;
        this.bootloader = bootloader_1.default;
        this.packages = packages_1.default;
        this.removeInstallerLink = remove_installer_link_1.default;
        // luksbootkeyfile:
        // plymouthcfg;
        this.initramfsCfg = initramfs_cfg_1.default;
        this.initramfs = initramfs_1.default;
        this.delLiveUser = del_live_user_1.default;
        this.umountFs = mount_fs_1.umountFs;
        this.umountVfs = mount_vfs_1.umountVfs;
        // to order in same way
        this.timezone = m_timezone_1.default;
        this.umount = umount_1.default;
        this.mkfs = mkfs_1.default;
        this.hostname = hostname_1.default;
        this.installer = {};
        this.installTarget = '/tmp/calamares-krill-root';
        this.verbose = false;
        this.echo = {};
        this.efi = false;
        this.devices = {};
        this.users = {};
        this.network = {};
        this.partitions = {};
        this.language = '';
        this.region = '';
        this.zone = '';
        this.keyboardModel = '';
        this.keyboardLayout = '';
        this.keyboardVariant = '';
        this.toNull = ' > /dev/null 2>&1';
        this.settings = {};
        this.remix = {};
        this.distro = {};
        // Crypted Clone
        this.luksName = 'luks-eggs-data';
        this.luksFile = `/run/live/medium/live/${this.luksName}`;
        this.luksDevice = `/dev/mapper/${this.luksName}`;
        this.luksMountpoint = `/mnt`;
        // Clone (Uncrypted)
        this.is_clone = fs_1.default.existsSync('/etc/penguins-eggs.d/is_clone');
        this.is_crypted_clone = fs_1.default.existsSync('/etc/penguins-eggs.d/is_crypted_clone');
        this.unattended = false;
        this.nointeractive = false;
        this.halt = false;
        this.cliAutologin = new cli_autologin_1.default();
        this.installer = (0, installer_1.installer)();
        this.settings = new settings_1.default();
        this.language = location.language;
        this.region = location.region;
        this.zone = location.zone;
        this.keyboardModel = keyboard.keyboardModel;
        this.keyboardLayout = keyboard.keyboardLayout;
        this.keyboardVariant = keyboard.keyboardVariant;
        this.network = network;
        this.partitions = partitions;
        this.users = users;
        this.devices.efi = {};
        this.devices.boot = {};
        this.devices.root = {};
        this.devices.data = {};
        this.devices.swap = {};
        this.distro = new distro_1.default(this.remix);
        this.efi = fs_1.default.existsSync('/sys/firmware/efi/efivars');
    }
    /**
     * install
     * @param verbose
     * @param umount
     * @returns
     */
    async start(domain = '', unattended = false, nointeractive = false, halt = false, verbose = false) {
        // Imposta il domain per flag
        if (domain !== '') {
            if (domain.at(0) !== '.') {
                domain = '.' + domain;
            }
            this.network.domain = domain;
        }
        /**
         * To let krill to work with Arch we need:
         */
        if (this.distro.familyId === 'archlinux') {
            if (this.distro.distroId === 'ManjaroLinux') {
                await (0, utils_2.exec)(`sudo ln -s /run/miso/bootmnt/live/ /live`);
            }
            else {
                await (0, utils_2.exec)(`sudo ln -s /run/archiso/bootmnt/live/ /live`);
            }
        }
        this.unattended = unattended;
        this.nointeractive = nointeractive;
        this.halt = halt;
        this.verbose = verbose;
        this.echo = utils_1.default.setEcho(this.verbose);
        if (this.verbose) {
            this.toNull = '';
        }
        // start
        await this.settings.load();
        // partition
        let percent = 0.0;
        let message = "";
        let isPartitioned = false;
        message = "Creating partitions";
        percent = 0.03;
        try {
            await redraw(react_1.default.createElement(install_1.default, { message: message, percent: percent }));
            isPartitioned = await this.partition();
        }
        catch (error) {
            await utils_1.default.pressKeyToExit(JSON.stringify(error));
        }
        if (isPartitioned) {
            // formatting
            message = "Formatting file system ";
            percent = 0.06;
            try {
                await redraw(react_1.default.createElement(install_1.default, { message: message, percent: percent }));
                await this.mkfs();
            }
            catch (error) {
                await utils_1.default.pressKeyToExit(JSON.stringify(error));
            }
            // mountFs
            message = "Mounting target file system ";
            percent = 0.09;
            try {
                redraw(react_1.default.createElement(install_1.default, { message: message, percent: percent }));
                await this.mountFs();
            }
            catch (error) {
                await utils_1.default.pressKeyToExit(JSON.stringify(error));
            }
            // mountVfs
            message = "Mounting on target VFS ";
            percent = 0.12;
            try {
                await redraw(react_1.default.createElement(install_1.default, { message: message, percent: percent }));
                await this.mountVfs();
            }
            catch (error) {
                await utils_1.default.pressKeyToExit(JSON.stringify(error));
            }
            // unpackfs
            message = "Unpacking filesystem ";
            percent = 0.15;
            try {
                await redraw(react_1.default.createElement(install_1.default, { message: message, percent: percent }));
                await this.unpackfs();
            }
            catch (error) {
                await utils_1.default.pressKeyToExit(JSON.stringify(error));
            }
            // dpkg-unsafe-io
            if (this.distro.familyId === 'debian') {
                message = "dpkg-unsafe-io";
                percent = 0.40;
                try {
                    await redraw(react_1.default.createElement(install_1.default, { message: message, percent: percent }));
                    await this.execCalamaresModule('dpkg-unsafe-io');
                }
                catch (error) {
                    await utils_1.default.pressKeyToExit(JSON.stringify(error));
                }
            }
            // sources-yolk
            if (this.distro.familyId === 'debian') {
                message = 'sources-yolk';
                percent = 0.43;
                try {
                    await redraw(react_1.default.createElement(install_1.default, { message: message, percent: percent, spinner: true }));
                    await this.execCalamaresModule('sources-yolk');
                }
                catch (error) {
                    await utils_1.default.pressKeyToExit(JSON.stringify(error));
                }
            }
            // machineid
            message = 'machineid';
            percent = 0.46;
            try {
                await redraw(react_1.default.createElement(install_1.default, { message: message, percent: percent, spinner: true }));
                await this.machineId();
            }
            catch (error) {
                await utils_1.default.pressKeyToExit(JSON.stringify(error));
            }
            // fstab
            message = "Creating fstab ";
            percent = 0.49;
            try {
                await redraw(react_1.default.createElement(install_1.default, { message: message, percent: percent }));
                await this.fstab(this.partitions.installationDevice);
            }
            catch (error) {
                await utils_1.default.pressKeyToExit(JSON.stringify(error));
            }
            /**
             * CryptedClone exec eggs syncfrom
             */
            if (this.is_crypted_clone) {
                message = "Restore private data from crypted clone ";
                if (fs_1.default.existsSync(this.luksFile)) {
                    percent = 0.55;
                    let cmd = `eggs syncfrom --rootdir /tmp/calamares-krill-root/ --file ${this.luksFile}`;
                    try {
                        await redraw(react_1.default.createElement(install_1.default, { message: message, percent: percent, spinner: true }));
                        await (0, utils_2.exec)(cmd, utils_1.default.setEcho(true));
                        this.is_clone = true; // Adesso è un clone
                    }
                    catch (error) {
                        await utils_1.default.pressKeyToExit(cmd);
                    }
                }
                else {
                    await utils_1.default.pressKeyToExit(`Cannot find LUKS file ${this.luksFile}`);
                }
            }
            // networkcfg
            message = "networkcfg";
            percent = 0.61;
            try {
                await this.networkCfg();
            }
            catch (error) {
                await utils_1.default.pressKeyToExit(JSON.stringify(error));
            }
            // hostname
            message = "Create hostname ";
            percent = 0.64;
            try {
                await redraw(react_1.default.createElement(install_1.default, { message: message, percent: percent }));
                await this.hostname(this.network.domain);
            }
            catch (error) {
                await utils_1.default.pressKeyToExit(JSON.stringify(error));
            }
            // initramfsCfg
            message = "initramfs configure";
            percent = 0.67;
            try {
                await redraw(react_1.default.createElement(install_1.default, { message: message, percent: percent }));
                await this.initramfsCfg(this.partitions.installationDevice);
            }
            catch (error) {
                await utils_1.default.pressKeyToExit(JSON.stringify(error));
            }
            // initramfs
            message = "initramfs ";
            percent = 0.70;
            try {
                await redraw(react_1.default.createElement(install_1.default, { message: message, percent: percent }));
                await this.initramfs();
            }
            catch (error) {
                await utils_1.default.pressKeyToExit(JSON.stringify(error));
            }
            // dpkg-unsafe-io-undo
            if (this.distro.familyId === 'debian') {
                message = "dpkg-unsafe-io-undo";
                percent = 0.72;
                try {
                    await redraw(react_1.default.createElement(install_1.default, { message: message, percent: percent }));
                    await this.execCalamaresModule('dpkg-unsafe-io-undo');
                }
                catch (error) {
                    await utils_1.default.pressKeyToExit(JSON.stringify(error));
                }
            }
            /**
             * IF NOT CLONE:
             * - locale
             * - keyboard
             * - localeCfg
             * - delLiveUser
             * - adduser
             * - autologin
             */
            if (!this.is_clone) {
                // locale
                message = "Locale";
                percent = 0.74;
                try {
                    redraw(react_1.default.createElement(install_1.default, { message: message, percent: percent }));
                    await this.locale();
                }
                catch (error) {
                    await utils_1.default.pressKeyToExit(JSON.stringify(error));
                }
                // keyboard
                message = "settings keyboard";
                percent = 0.75;
                try {
                    await this.keyboard();
                }
                catch (error) {
                    await utils_1.default.pressKeyToExit(JSON.stringify(error));
                }
                // localeCfg
                message = "Locale Configuration";
                percent = 0.76;
                try {
                    await this.localeCfg();
                    await (0, utils_2.exec)("chroot " + this.installTarget + " locale-gen");
                }
                catch (error) {
                    await utils_1.default.pressKeyToExit(JSON.stringify(error));
                }
                // delLiveUser
                message = "Remove user LIVE";
                percent = 0.75;
                try {
                    await redraw(react_1.default.createElement(install_1.default, { message: message, percent: percent }));
                    await this.delLiveUser();
                }
                catch (error) {
                    await utils_1.default.pressKeyToExit(JSON.stringify(error));
                }
                // addUser
                message = "Add user";
                percent = 0.76;
                try {
                    await redraw(react_1.default.createElement(install_1.default, { message: message, percent: percent }));
                    await this.addUser(this.users.name, this.users.password, this.users.fullname, '', '', '');
                }
                catch (error) {
                    await utils_1.default.pressKeyToExit(JSON.stringify(error));
                }
                // changePassword root
                message = "Add root password";
                percent = 0.77;
                try {
                    await redraw(react_1.default.createElement(install_1.default, { message: message, percent: percent }));
                    await this.changePassword('root', this.users.rootPassword);
                }
                catch (error) {
                    await utils_1.default.pressKeyToExit(JSON.stringify(error));
                }
                // autologin
                if (pacman_1.default.isInstalledGui()) {
                    try {
                        message = "Autologin GUI";
                        percent = 0.78;
                        if (this.users.autologin) {
                            await xdg_1.default.autologin(await utils_1.default.getPrimaryUser(), this.users.name, this.installTarget);
                            if (this.distro.distroLike === 'Arch') {
                                await (0, utils_2.exec)(`chroot ${this.installTarget} groupadd autologin`);
                                await (0, utils_2.exec)(`chroot ${this.installTarget} gpasswd -a ${this.users.name} autologin`);
                            }
                        }
                        await redraw(react_1.default.createElement(install_1.default, { message: message, percent: percent }));
                    }
                    catch (error) {
                        await utils_1.default.pressKeyToExit(JSON.stringify(error));
                    }
                }
            } // IF NOT CLONE END
            // Remove ALWAYS autologin CLI
            message = "Remove autologin CLI";
            percent = 0.80;
            try {
                await redraw(react_1.default.createElement(install_1.default, { message: message, percent: percent }));
                await this.cliAutologin.remove(this.installTarget);
            }
            catch (error) {
                await utils_1.default.pressKeyToExit(JSON.stringify(error));
            }
            // bootloader-config
            message = "bootloader-config ";
            percent = 0.82;
            try {
                await redraw(react_1.default.createElement(install_1.default, { message: message, percent: percent }));
                await this.bootloaderConfig();
            }
            catch (error) {
                await utils_1.default.pressKeyToExit(JSON.stringify(error));
            }
            // grubcfg
            message = "grubcfg ";
            percent = 0.84;
            try {
                await redraw(react_1.default.createElement(install_1.default, { message: message, percent: percent }));
                await this.grubcfg();
            }
            catch (error) {
                await utils_1.default.pressKeyToExit(JSON.stringify(error));
            }
            // bootloader (grub-install)
            message = "bootloader ";
            percent = 0.86;
            try {
                await redraw(react_1.default.createElement(install_1.default, { message: message, percent: percent }));
                await this.bootloader();
            }
            catch (error) {
                await utils_1.default.pressKeyToExit(JSON.stringify(error));
            }
            // sources-yolk-undo
            if (this.distro.familyId === 'debian') {
                message = "sources-yolk-undo";
                percent = 0.88;
                try {
                    await redraw(react_1.default.createElement(install_1.default, { message: message, percent: percent }));
                    await this.execCalamaresModule('sources-yolk-undo');
                }
                catch (error) {
                    await utils_1.default.pressKeyToExit(JSON.stringify(error));
                }
            }
            // packages
            message = "add/remove packages";
            percent = 0.90;
            try {
                await redraw(react_1.default.createElement(install_1.default, { message: message, percent: percent }));
                await this.packages();
            }
            catch (error) {
                console.log(JSON.stringify(error));
            }
            /**
             *
             * remove CLI/GUI installer link
             */
            message = "remove GUI installer link";
            percent = 0.92;
            try {
                await redraw(react_1.default.createElement(install_1.default, { message: message, percent: percent }));
                await this.removeInstallerLink();
            }
            catch (error) {
                await utils_1.default.pressKeyToExit(JSON.stringify(error));
            }
            // remove /etc/penguins_eggs.d/is_clone*
            message = "Cleanup";
            percent = 0.94;
            try {
                await redraw(react_1.default.createElement(install_1.default, { message: message, percent: percent }));
                await (0, utils_2.exec)(`rm -f ${this.installTarget}/etc/penguins-eggs.d/is_clone`);
                await (0, utils_2.exec)(`rm -f ${this.installTarget}/etc/penguins-eggs.d/is_crypted_clone`);
            }
            catch (error) {
                await utils_1.default.pressKeyToExit(JSON.stringify(error));
            }
            /**
             * custom final steps
             */
            const cfs = new cfs_1.default();
            const steps = await cfs.steps();
            if (steps.length > 0) {
                for (const step of steps) {
                    message = `running ${step}`;
                    percent = 0.97;
                    try {
                        await redraw(react_1.default.createElement(install_1.default, { message: message, percent: percent }));
                        await this.execCalamaresModule(step);
                    }
                    catch (error) {
                        await utils_1.default.pressKeyToExit(JSON.stringify(error));
                    }
                }
            }
            // umountVfs
            message = "umount VFS";
            percent = 0.96;
            try {
                await redraw(react_1.default.createElement(install_1.default, { message: message, percent: percent }));
                await this.umountVfs();
            }
            catch (error) {
                await utils_1.default.pressKeyToExit(JSON.stringify(error));
            }
            message = "umount";
            percent = 0.98;
            try {
                await redraw(react_1.default.createElement(install_1.default, { message: message, percent: percent }));
                await this.umountFs();
            }
            catch (error) {
                await utils_1.default.pressKeyToExit(JSON.stringify(error));
            }
            // finished
            message = "finished";
            percent = 100.0;
            try {
                await redraw(react_1.default.createElement(install_1.default, { message: message, percent: percent }));
                await this.finished();
            }
            catch (error) {
                await utils_1.default.pressKeyToExit(JSON.stringify(error));
            }
        }
    }
    /**
     *
     */
    async execCalamaresModule(name) {
        const moduleName = this.installer.multiarchModules + name + '/module.desc';
        if (fs_1.default.existsSync(moduleName)) {
            const calamaresModule = js_yaml_1.default.load(fs_1.default.readFileSync(moduleName, 'utf8'));
            let command = calamaresModule.command;
            if (command !== '' || command !== undefined) {
                command += this.toNull;
                await (0, utils_2.exec)(command, this.echo);
            }
        }
    }
    /**
     * only show the result
     */
    async finished() {
        await redraw(react_1.default.createElement(finished_1.default, { installationDevice: this.partitions.installationDevice, hostName: this.users.hostname, userName: this.users.name }));
        let cmd = "reboot";
        if (this.halt) {
            cmd = "poweroff";
        }
        if (this.unattended && this.nointeractive) {
            console.log(`System will ${cmd} in 5 seconds...`);
            await sleep(5000);
            await (0, utils_2.exec)(cmd, { echo: true });
        }
        else {
            utils_1.default.pressKeyToExit(`Press a key to ${cmd}`);
            await (0, utils_2.exec)(cmd, { echo: true });
        }
    }
}
exports.default = Sequence;
// const ifaces: string[] = fs.readdirSync('/sys/class/net/')
/**
 *
 * @param elem
 */
async function redraw(elem) {
    let opt = {};
    opt.patchConsole = false;
    opt.debug = false;
    console.clear();
    // await exec('clear', Utils.setEcho(false))
    (0, ink_1.render)(elem, opt);
}
/**
 *
 * @param ms
 * @returns
 */
function sleep(ms = 0) {
    return new Promise((resolve) => {
        setTimeout(resolve, ms);
    });
}
