/**
 * Text Processor Module
 * Handles text formatting and typography enhancements like smart quotes and hyphenation
 */
import { BaseModule } from './base-module.js';
import { moduleRegistry } from './module-registry.js';

class TextProcessorModule extends BaseModule {
    constructor() {
        super('text-processor', 'Text Processor');
        this.smartyPants = null; // Store the function reference here
        this.smartypantsu = null; // Store the function reference here
        this.hyphenator = null; // For hyphenation function
        this.hyphenatorReady = false;
        this.locale = 'en-us';
    }

    /**
     * Load module dependencies
     * @returns {Promise<boolean>} - Resolves with success status
     */
    async loadDependencies() {
        try {
            this.reportProgress(10, "Loading dependencies");

            // Load SmartyPants script dynamically
            await this.loadSmartyPantsScript();
            this.reportProgress(50, "SmartyPants loaded");

            // Initialize hyphenation in the background, but don't wait for it
            this.initializeHyphenation();

            this.reportProgress(90, "Dependencies loaded");
            return true;
        } catch (error) {
            console.error("Error loading Text Processor dependencies:", error);
            return false;
        }
    }

    /**
     * Load the SmartyPants script dynamically and wait for it to be ready
     * @returns {Promise<void>}
     */
    loadSmartyPantsScript() {
        return new Promise((resolve, reject) => {
            // Check if already loaded globally
            if (typeof window.SmartyPants === 'object' && typeof window.SmartyPants.smartypants === 'function') {
                this.smartyPants = window.SmartyPants.smartypants;
                this.smartypantsu = window.SmartyPants.smartypantsu;
                console.log("SmartyPants already loaded globally");
                resolve();
                return;
            }

            // Load the script using a script tag
            const script = document.createElement('script');
            script.src = '/js/smartypants.js';
            script.async = false; // Load synchronously relative to other scripts

            script.onload = () => {
                // Use a microtask to ensure the script has executed
                Promise.resolve().then(() => {
                    if (typeof window.SmartyPants === 'object' && typeof window.SmartyPants.smartypants === 'function') {
                        this.smartyPants = window.SmartyPants.smartypants;
                        this.smartypantsu = window.SmartyPants.smartypantsu;
                        console.log("SmartyPants loaded successfully via script tag");
                        resolve();
                    } else {
                        console.error("SmartyPants script loaded but functions not found on window.SmartyPants");
                        reject(new Error('SmartyPants functions not found after loading'));
                    }
                });
            };

            script.onerror = () => {
                console.error('Failed to load smartypants.js script');
                reject(new Error('Failed to load smartypants.js script'));
            };

            document.head.appendChild(script);
        });
    }

    /**
     * Initialize the module
     * @returns {Promise<boolean>} - Resolves with success status
     */
    async initialize() {
        try {
            this.reportProgress(70, "Initializing text processor");

            // Get locale from Localization module if available
            const localizationModule = moduleRegistry.getModule('localization');
            if (localizationModule) {
                this.locale = localizationModule.getLocale();
                // Register as an observer for locale changes
                localizationModule.registerObserver(this, (newLocale) => {
                    this.setLocale(newLocale);
                });
            }

            // Ensure global locale is set for SmartyPants
            window.locale = this.locale;

            // Verify SmartyPants is available via the stored references
            if (typeof this.smartyPants !== 'function') {
                console.error("SmartyPants function not available for initialization");
                return false;
            }

            // Final initialization steps
            this.reportProgress(100, "Text processor ready");
            return true;
        } catch (error) {
            console.error("Error initializing Text Processor:", error);
            return false;
        }
    }

    /**
     * Initialize hyphenation using Hyphenopoly
     */
    initializeHyphenation() {
        // Create custom events for hyphenation loading status
        const hyphenationLoadedEvent = new CustomEvent('hyphenation-loaded');

        // Add listener for hyphenation loaded event
        document.addEventListener('hyphenation-loaded', () => {
            console.log('Hyphenation module loaded');
            this.hyphenatorReady = true;
        }, { once: true });

        // Check if Hyphenopoly is loaded
        if (window.Hyphenopoly) {
            this.setupHyphenopoly();
        } else {
            // Set up listener for when Hyphenopoly might be loaded later
            window.addEventListener('hyphenopoly-loaded', () => {
                this.setupHyphenopoly();
            });

            // Try loading Hyphenopoly if not already loading
            if (!document.querySelector('script[src*="Hyphenopoly_Loader.js"]')) {
                this.loadHyphenopolyScript();
            }
        }
    }

    /**
     * Load the Hyphenopoly script
     */
    loadHyphenopolyScript() {
        // Create script element for loader
        const script = document.createElement('script');
        script.src = '/js/Hyphenopoly_Loader.js';
        script.async = true;

        script.onload = () => {
            document.dispatchEvent(new CustomEvent('hyphenopoly-script-loaded'));
        };

        script.onerror = (error) => {
            console.error('Failed to load Hyphenopoly:', error);
            document.dispatchEvent(new CustomEvent('hyphenation-error', {
                detail: { error: 'Failed to load Hyphenopoly script' }
            }));
        };

        document.head.appendChild(script);

        // Set up configuration for Hyphenopoly
        window.Hyphenopoly = {
            require: {
                'en-us': 'FORCEHYPHENATION'
            },
            paths: {
                maindir: '/js/',
                patterndir: '/js/patterns/'
            },
            setup: {
                selectors: {
                    '.hyphenate': {}
                }
            }
        };
    }

    /**
     * Set up Hyphenopoly when it's available
     */
    setupHyphenopoly() {
        // Wait for hyphenator to be available
        if (window.Hyphenopoly && window.Hyphenopoly.hyphenators) {
            // Get hyphenator for English
            window.Hyphenopoly.hyphenators['en-us'].then((hyphenator) => {
                console.log('Hyphenator ready');
                this.hyphenator = hyphenator;
                this.hyphenatorReady = true;

                // Dispatch event that hyphenation is ready
                document.dispatchEvent(new CustomEvent('hyphenation-loaded'));
            }).catch(err => {
                console.error('Error loading hyphenator:', err);
            });
        }
    }

    /**
     * Set the hyphenator function
     * @param {Function} hyphenatorFunc - The hyphenator function
     */
    setHyphenator(hyphenatorFunc) {
        if (typeof hyphenatorFunc === 'function') {
            this.hyphenator = hyphenatorFunc;
            this.hyphenatorReady = true;
            console.log("Hyphenator function set explicitly");
        } else {
            console.warn("Invalid hyphenator provided");
        }
    }

    /**
     * Process text with SmartyPants and optional hyphenation
     * @param {string} text - The text to process
     * @param {boolean} useHyphenation - Whether to apply hyphenation
     * @returns {string} - The processed text
     */
    process(text, useHyphenation = false) {
        if (!text) return '';

        let processed = text;

        // Apply SmartyPants for typographic punctuation using stored references
        try {
            if (typeof this.smartyPants === 'function') {
                processed = this.smartyPants(processed);
            } else {
                 console.warn("SmartyPants function not available for processing");
            }

            // Convert HTML entities to UTF-8 characters
            if (typeof this.smartypantsu === 'function') {
                processed = this.smartypantsu(processed);
            } else {
                 console.warn("smartypantsu function not available for processing");
            }
        } catch (error) {
            console.error("Error applying SmartyPants:", error);
        }

        // Apply hyphenation if enabled and available
        if (useHyphenation && this.hyphenatorReady && this.hyphenator) {
            try {
                processed = this.hyphenator(processed);
            } catch (error) {
                console.error("Error applying hyphenation:", error);
            }
        }

        return processed;
    }

    /**
     * Check if hyphenation is available
     * @returns {boolean} - Whether hyphenation is available
     */
    isHyphenationAvailable() {
        return this.hyphenatorReady && this.hyphenator !== null;
    }

    /**
     * Apply only hyphenation to text
     * @param {string} text - The text to hyphenate
     * @returns {string} - The hyphenated text
     */
    hyphenate(text) {
        if (!text || !this.hyphenatorReady || !this.hyphenator) {
            return text;
        }

        try {
            return this.hyphenator(text);
        } catch (error) {
            console.error("Error hyphenating text:", error);
            return text;
        }
    }

    /**
     * Set the locale for text processing
     * @param {string} locale - The locale code (e.g., 'en-us', 'de')
     */
    setLocale(locale) {
        if (locale && typeof locale === 'string') {
            this.locale = locale.toLowerCase();
            // Update global locale for SmartyPants
            window.locale = this.locale;
            console.log(`TextProcessor: Locale set to ${locale}`);
        }
    }
}

// Create the singleton instance
const TextProcessor = new TextProcessorModule();

// Register with the module registry
moduleRegistry.register(TextProcessor);

// Export the module
export { TextProcessor };

// Keep a reference in window for loader system
window.TextProcessor = TextProcessor;
