"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const node_os_1 = require("node:os");
const node_path_1 = require("node:path");
const promises_1 = require("node:fs/promises");
const types_1 = require("./types");
const Connection_1 = __importDefault(require("./Connection"));
const LocalWatcher_1 = __importDefault(require("./LocalWatcher"));
const FileWatcher_1 = __importDefault(require("./FileWatcher"));
const RemoteWatcher_1 = __importDefault(require("./RemoteWatcher"));
const Queue_1 = require("./queues/Queue");
const Password_1 = __importDefault(require("./Password"));
const commands_1 = require("./commands");
const transform_1 = __importDefault(require("./transform"));
const Local_1 = require("./Local");
const URI_1 = require("./utils/URI");
class App {
    static async bootstrap(handle, emitter, opener) {
        const dataPath = (0, node_path_1.join)((0, node_os_1.homedir)(), '.f5');
        const connPath = (0, node_path_1.join)(dataPath, 'connections');
        (0, promises_1.mkdir)(connPath, { recursive: true });
        (0, Local_1.touch)((0, node_path_1.join)(dataPath, 'credentials.json'), JSON.stringify([]));
        const settingsPath = (0, node_path_1.join)(dataPath, 'settings.json');
        if (!(0, Local_1.stat)(settingsPath)) {
            await (0, Local_1.touch)(settingsPath);
            commands_1.commands.saveSettings(settingsPath, await commands_1.commands.getSettings(settingsPath));
        }
        Password_1.default.load(dataPath, id => App.onError({ type: types_1.FailureType.Unauthorized, id }));
        Connection_1.default.initialize();
        Object.entries({
            getapp: () => commands_1.commands.getSettings(settingsPath),
            saveapp: ({ settings }) => commands_1.commands.saveSettings(settingsPath, settings),
            connect: ({ file }) => commands_1.commands.connect(file, (id, { message }) => this.onError({ type: types_1.FailureType.RemoteError, id, message })),
            login: ({ id, password, remember }) => Password_1.default.set(id, password, remember),
            disconnect: ({ id, sid }) => commands_1.commands.disconnect(id, sid),
            watch: ({ dir }) => commands_1.commands.watch(dir, this.localWatcher, this.remoteWatcher, this.fileWatcher),
            unwatch: ({ dir }) => commands_1.commands.unwatch(dir, this.localWatcher, this.remoteWatcher, this.fileWatcher),
            refresh: ({ dir }) => this.remoteWatcher.refresh(dir),
            copy: ({ src, dest, move, filter, sid }) => commands_1.commands.copy(src, dest, move, filter, sid),
            duplicate: ({ src, filter }) => commands_1.commands.duplicate(src, filter),
            remove: ({ files, force }) => commands_1.commands.remove(files, force, connPath),
            clear: ({ file, force }) => commands_1.commands.clear(file, force),
            open: ({ file }) => opener(file),
            mkdir: ({ name, parent }) => commands_1.commands.mkdir(name, parent),
            read: ({ file }) => commands_1.commands.read(file),
            write: ({ path, content }) => commands_1.commands.write(path, content),
            rename: ({ path, name }) => commands_1.commands.rename(path, name),
            get: ({ path }) => commands_1.commands.getConnection(path),
            save: ({ path, settings }) => commands_1.commands.saveConnection(path, settings),
            resolve: ({ id, action, forAll, sid }) => commands_1.commands.resolve(id, action, forAll, sid),
            stop: ({ id }) => Queue_1.queues.get(id)?.stop()
        }).forEach(([name, handler]) => handle(name, handler));
        const emitError = emitter('error');
        this.onError = (error) => emitError(error);
        const emitDir = emitter('dir');
        const sendDirContent = (uri, files) => emitDir({ uri, files });
        this.localWatcher = new LocalWatcher_1.default((path, files) => sendDirContent((0, URI_1.createURI)(types_1.LocalFileSystemID, path), files.map(f => ({ ...f, URI: (0, URI_1.createURI)(types_1.LocalFileSystemID, f.path) }))), path => this.onError({ type: types_1.FailureType.MissingDir, uri: (0, URI_1.createURI)(types_1.LocalFileSystemID, path) }));
        this.remoteWatcher = new RemoteWatcher_1.default(sendDirContent, uri => this.onError({ type: types_1.FailureType.MissingDir, uri }), transform_1.default);
        const emitFile = emitter('file');
        const sendFileStat = (path, stat) => emitFile({ path, stat });
        this.fileWatcher = new FileWatcher_1.default(sendFileStat);
        const emitQueue = emitter('queue');
        this.onQueueUpdate = (id, event) => emitQueue({ id, event });
    }
}
exports.default = App;
