/**
 * 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
        });
    }
}
