/** * Base Module Class * Provides common functionality and enforces a consistent interface for all modules */ export class BaseModule { constructor(id, name) { this.id = id; this.name = name; this.state = 'PENDING'; this.progress = 0; this.progressCallback = null; } /** * Initialize the module interface * @param {Function} progressCallback - Function to report progress * @returns {Promise} - Resolves when initialization is complete */ async initializeInterface(progressCallback) { this.progressCallback = progressCallback; try { this.changeState('LOADING'); this.reportProgress(10, "Starting initialization"); // Load dependencies const depsLoaded = await this.loadDependencies(); if (!depsLoaded) { this.changeState('ERROR'); this.reportProgress(100, "Failed to load dependencies"); return false; } const depStatus = await this.waitForDependencies(); if (!depStatus) { // If dependencies aren't available, report waiting this.changeState('WAITING'); return Promise.resolve(false); } this.changeState('INITIALIZING'); const initResult = await this.initialize(); if (initResult) { this.changeState('FINISHED'); this.reportProgress(100, "Initialization complete"); } else { this.changeState('ERROR'); this.reportProgress(100, "Initialization failed"); } return initResult; } catch (error) { console.error(`Error in module ${this.id}:`, error); this.changeState('ERROR'); this.reportProgress(100, "Error during initialization"); return Promise.resolve(false); } } /** * Load module dependencies - Override this in child classes * @returns {Promise} - Resolves when dependencies are loaded */ async loadDependencies() { return Promise.resolve(true); } /** * Wait for dependencies to be ready - Override this in child classes * @returns {Promise} - Resolves when dependencies are ready */ async waitForDependencies() { return Promise.resolve(true); } /** * Initialize the module - Override this in child classes * @returns {Promise} - Resolves when initialization is complete */ async initialize() { return Promise.resolve(true); } /** * Change the module state and dispatch an event * @param {string} state - The new state */ changeState(state) { this.state = state; document.dispatchEvent(new ModuleEvent('stateChange', this.id, { state })); } /** * Report progress to the module loader * @param {number} percent - Progress percentage (0-100) * @param {string} message - Status message */ reportProgress(percent, message) { this.progress = percent; if (this.progressCallback && typeof this.progressCallback === 'function') { this.progressCallback(percent, message); } else { document.dispatchEvent(new ModuleEvent('progress', this.id, { progress: percent })); if (message) { document.dispatchEvent(new ModuleEvent('message', this.id, { message })); } } } /** * Get the current module state * @returns {string} - Current state */ getState() { return this.state; } } /** * Module Events - Used for communication between modules and the loader */ export class ModuleEvent extends CustomEvent { constructor(type, moduleId, data = {}) { super(`module:${type}`, { detail: { moduleId, ...data }, bubbles: true }); } }