"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.NVM_BACKUP_PREFIX = void 0;
const store_1 = __importDefault(require("../config/store"));
const logger_1 = require("./logger");
const jsonStore_1 = __importStar(require("./jsonStore"));
const croner_1 = __importDefault(require("croner"));
const promises_1 = require("fs/promises");
const app_1 = require("../config/app");
const utils_1 = require("./utils");
exports.NVM_BACKUP_PREFIX = 'NVM_';
const logger = (0, logger_1.module)('Backup');
class BackupManager {
    config;
    storeJob;
    nvmJob;
    zwaveClient;
    get default() {
        return {
            storeBackup: false,
            storeCron: '0 0 * * *',
            storeKeep: 7,
            nvmBackup: false,
            nvmBackupOnEvent: false,
            nvmCron: '0 0 * * *',
            nvmKeep: 7,
        };
    }
    get backupOnEvent() {
        return this.config.nvmBackupOnEvent;
    }
    nextRun(job) {
        if (job?.nextRun()) {
            return job.nextRun().toLocaleString();
        }
        return 'UNKNOWN';
    }
    init(zwaveClient) {
        this.config = {
            ...this.default,
            ...jsonStore_1.default.get(store_1.default.settings).backup,
        };
        this.zwaveClient = zwaveClient;
        if (this.storeJob) {
            this.storeJob.stop();
        }
        if (!this.config.storeBackup) {
            logger.warn('Store backup is disabled');
        }
        else {
            this.storeJob = new croner_1.default(this.config.storeCron, this.backupStore.bind(this));
            logger.info(`Backup job started with cron: ${this.config.storeCron}. Next run: ${this.nextRun(this.storeJob)}`);
        }
        if (this.nvmJob) {
            this.nvmJob.stop();
        }
        if (!this.config.nvmBackup) {
            logger.warn('Nvm backup is disabled');
        }
        else {
            this.nvmJob = new croner_1.default(this.config.nvmCron, this.backupNvm.bind(this));
            logger.info(`Backup job started with cron: ${this.config.nvmCron}. Next run: ${this.nextRun(this.nvmJob)}`);
        }
    }
    async backupNvm() {
        logger.info('Backup NVM started');
        try {
            const { fileName } = await this.zwaveClient.backupNVMRaw();
            logger.info(`Backup NVM created: ${fileName}`);
            if (this.nvmJob) {
                logger.info(`Next NVM backup: ${this.nextRun(this.nvmJob)}`);
            }
            // cleanup backups dir, keep last backup files
            const backups = (await (0, promises_1.readdir)(app_1.nvmBackupsDir)).filter((f) => f.startsWith(exports.NVM_BACKUP_PREFIX));
            // keep last `keep` backups
            if (backups.length > this.config.nvmKeep) {
                const toDelete = backups.slice(0, backups.length - this.config.nvmKeep);
                await Promise.all(toDelete.map(async (file) => (0, promises_1.unlink)((0, utils_1.joinPath)(app_1.nvmBackupsDir, file))));
                logger.info(`Deleted ${toDelete.length} old NVM backups`);
            }
        }
        catch (err) {
            logger.error('Backup NVM failed', err);
        }
    }
    async backupStore() {
        logger.info('Backup STORE started');
        try {
            const backupFile = await jsonStore_1.default.backup();
            logger.info(`Backup STORE created: ${backupFile}`);
            if (this.storeJob) {
                logger.info(`Next STORE backup: ${this.nextRun(this.storeJob)}`);
            }
            // cleanup backups dir, keep last backup files
            const backups = (await (0, promises_1.readdir)(app_1.storeBackupsDir)).filter((f) => f.startsWith(jsonStore_1.STORE_BACKUP_PREFIX));
            // keep last `keep` backups
            if (backups.length > this.config.storeKeep) {
                const toDelete = backups.slice(0, backups.length - this.config.storeKeep);
                await Promise.all(toDelete.map(async (file) => (0, promises_1.unlink)((0, utils_1.joinPath)(app_1.storeBackupsDir, file))));
                logger.info(`Deleted ${toDelete.length} old STORE backups`);
            }
        }
        catch (err) {
            logger.error('Backup STORE failed', err);
        }
    }
}
exports.default = new BackupManager();
