/**
 * ThrillWiki Map Integration - Master Integration Script
 * 
 * This module coordinates all map components, handles initialization order,
 * manages component communication, and provides a unified API
 */

class MapIntegration {
    constructor(options = {}) {
        this.options = {
            autoInit: true,
            enableLogging: true,
            enablePerformanceMonitoring: true,
            initTimeout: 10000,
            retryAttempts: 3,
            components: {
                maps: true,
                filters: true,
                roadtrip: true,
                geolocation: true,
                markers: true,
                htmx: true,
                mobileTouch: true,
                darkMode: true
            },
            ...options
        };
        
        this.components = {};
        this.initOrder = [
            'darkMode',
            'mobileTouch', 
            'maps',
            'markers',
            'filters',
            'geolocation',
            'htmx',
            'roadtrip'
        ];
        this.initialized = false;
        this.initStartTime = null;
        this.errors = [];
        
        if (this.options.autoInit) {
            this.init();
        }
    }
    
    /**
     * Initialize all map components
     */
    async init() {
        this.initStartTime = performance.now();
        this.log('Starting map integration initialization...');
        
        try {
            // Wait for DOM to be ready
            await this.waitForDOM();
            
            // Initialize components in order
            await this.initializeComponents();
            
            // Connect components
            this.connectComponents();
            
            // Setup global event handlers
            this.setupGlobalHandlers();
            
            // Verify integration
            this.verifyIntegration();
            
            this.initialized = true;
            this.logPerformance();
            this.log('Map integration initialized successfully');
            
            // Emit ready event
            this.emitEvent('mapIntegrationReady', {
                components: Object.keys(this.components),
                initTime: performance.now() - this.initStartTime
            });
            
        } catch (error) {
            this.handleInitError(error);
        }
    }
    
    /**
     * Wait for DOM to be ready
     */
    waitForDOM() {
        return new Promise((resolve) => {
            if (document.readyState === 'loading') {
                document.addEventListener('DOMContentLoaded', resolve);
            } else {
                resolve();
            }
        });
    }
    
    /**
     * Initialize components in the correct order
     */
    async initializeComponents() {
        for (const componentName of this.initOrder) {
            if (!this.options.components[componentName]) {
                this.log(`Skipping ${componentName} (disabled)`);
                continue;
            }
            
            try {
                await this.initializeComponent(componentName);
                this.log(`✓ ${componentName} initialized`);
            } catch (error) {
                this.error(`✗ Failed to initialize ${componentName}:`, error);
                this.errors.push({ component: componentName, error });
            }
        }
    }
    
    /**
     * Initialize individual component
     */
    async initializeComponent(componentName) {
        switch (componentName) {
            case 'darkMode':
                if (window.DarkModeMaps) {
                    this.components.darkMode = window.darkModeMaps || new DarkModeMaps();
                }
                break;
                
            case 'mobileTouch':
                if (window.MobileTouchSupport) {
                    this.components.mobileTouch = window.mobileTouchSupport || new MobileTouchSupport();
                }
                break;
                
            case 'maps':
                // Look for existing map instances or create new ones
                if (window.thrillwikiMap) {
                    this.components.maps = window.thrillwikiMap;
                } else if (window.ThrillWikiMap) {
                    const mapContainer = document.getElementById('map-container');
                    if (mapContainer) {
                        this.components.maps = new ThrillWikiMap('map-container');
                        window.thrillwikiMap = this.components.maps;
                    }
                }
                break;
                
            case 'markers':
                if (window.MapMarkers && this.components.maps) {
                    this.components.markers = window.mapMarkers || new MapMarkers(this.components.maps);
                }
                break;
                
            case 'filters':
                if (window.MapFilters) {
                    const filterForm = document.getElementById('map-filters');
                    if (filterForm) {
                        this.components.filters = window.mapFilters || new MapFilters('map-filters');
                    }
                }
                break;
                
            case 'geolocation':
                if (window.UserLocation) {
                    this.components.geolocation = window.userLocation || new UserLocation();
                }
                break;
                
            case 'htmx':
                if (window.HTMXMapIntegration && typeof htmx !== 'undefined') {
                    this.components.htmx = window.htmxMapIntegration || new HTMXMapIntegration();
                }
                break;
                
            case 'roadtrip':
                if (window.RoadTripPlanner) {
                    const roadtripContainer = document.getElementById('roadtrip-planner');
                    if (roadtripContainer) {
                        this.components.roadtrip = window.roadTripPlanner || new RoadTripPlanner('roadtrip-planner');
                    }
                }
                break;
        }
    }
    
    /**
     * Connect components together
     */
    connectComponents() {
        this.log('Connecting components...');
        
        // Connect maps to other components
        if (this.components.maps) {
            // Connect to dark mode
            if (this.components.darkMode) {
                this.components.darkMode.registerMapInstance(this.components.maps);
            }
            
            // Connect to mobile touch
            if (this.components.mobileTouch) {
                this.components.mobileTouch.registerMapInstance(this.components.maps);
            }
            
            // Connect to geolocation
            if (this.components.geolocation) {
                this.components.geolocation.connectToMap(this.components.maps);
            }
            
            // Connect to road trip planner
            if (this.components.roadtrip) {
                this.components.roadtrip.connectToMap(this.components.maps);
            }
        }
        
        // Connect filters to other components
        if (this.components.filters) {
            // Connect to maps
            if (this.components.maps) {
                this.components.filters.connectToMap(this.components.maps);
            }
            
            // Connect to HTMX
            if (this.components.htmx) {
                this.components.htmx.connectToFilter(this.components.filters);
            }
        }
        
        // Connect HTMX to maps
        if (this.components.htmx && this.components.maps) {
            this.components.htmx.connectToMap(this.components.maps);
        }
    }
    
    /**
     * Setup global event handlers
     */
    setupGlobalHandlers() {
        // Handle global map events
        document.addEventListener('mapDataUpdate', (e) => {
            this.handleMapDataUpdate(e.detail);
        });
        
        // Handle filter changes
        document.addEventListener('filterChange', (e) => {
            this.handleFilterChange(e.detail);
        });
        
        // Handle theme changes
        document.addEventListener('themeChanged', (e) => {
            this.handleThemeChange(e.detail);
        });
        
        // Handle orientation changes
        document.addEventListener('orientationChanged', (e) => {
            this.handleOrientationChange(e.detail);
        });
        
        // Handle visibility changes for performance
        document.addEventListener('visibilitychange', () => {
            this.handleVisibilityChange();
        });
        
        // Handle errors
        window.addEventListener('error', (e) => {
            if (this.isMapRelatedError(e)) {
                this.handleGlobalError(e);
            }
        });
    }
    
    /**
     * Handle map data updates
     */
    handleMapDataUpdate(data) {
        if (this.components.maps) {
            this.components.maps.updateMarkers(data);
        }
    }
    
    /**
     * Handle filter changes
     */
    handleFilterChange(filters) {
        if (this.components.maps) {
            this.components.maps.updateFilters(filters);
        }
    }
    
    /**
     * Handle theme changes
     */
    handleThemeChange(themeData) {
        // All components should already be listening for this
        // Just log for monitoring
        this.log(`Theme changed to ${themeData.newTheme}`);
    }
    
    /**
     * Handle orientation changes
     */
    handleOrientationChange(orientationData) {
        // Invalidate map sizes after orientation change
        if (this.components.maps) {
            setTimeout(() => {
                this.components.maps.invalidateSize();
            }, 300);
        }
    }
    
    /**
     * Handle visibility changes
     */
    handleVisibilityChange() {
        const isHidden = document.hidden;
        
        // Pause/resume location watching
        if (this.components.geolocation) {
            if (isHidden) {
                this.components.geolocation.stopWatching();
            } else if (this.components.geolocation.options.watchPosition) {
                this.components.geolocation.startWatching();
            }
        }
    }
    
    /**
     * Check if error is map-related
     */
    isMapRelatedError(error) {
        const mapKeywords = ['leaflet', 'map', 'marker', 'tile', 'geolocation', 'htmx'];
        const errorMessage = error.message ? error.message.toLowerCase() : '';
        const errorStack = error.error && error.error.stack ? error.error.stack.toLowerCase() : '';
        
        return mapKeywords.some(keyword => 
            errorMessage.includes(keyword) || errorStack.includes(keyword)
        );
    }
    
    /**
     * Handle global errors
     */
    handleGlobalError(error) {
        this.error('Global map error:', error);
        this.errors.push({ type: 'global', error });
        
        // Emit error event
        this.emitEvent('mapError', { error, timestamp: Date.now() });
    }
    
    /**
     * Verify integration is working
     */
    verifyIntegration() {
        const issues = [];
        
        // Check required components
        if (this.options.components.maps && !this.components.maps) {
            issues.push('Maps component not initialized');
        }
        
        // Check component connections
        if (this.components.maps && this.components.darkMode) {
            if (!this.components.darkMode.mapInstances.has(this.components.maps)) {
                issues.push('Maps not connected to dark mode');
            }
        }
        
        // Check DOM elements
        const mapContainer = document.getElementById('map-container');
        if (this.components.maps && !mapContainer) {
            issues.push('Map container not found in DOM');
        }
        
        if (issues.length > 0) {
            this.warn('Integration issues found:', issues);
        }
        
        return issues.length === 0;
    }
    
    /**
     * Handle initialization errors
     */
    handleInitError(error) {
        this.error('Map integration initialization failed:', error);
        
        // Emit error event
        this.emitEvent('mapIntegrationError', { 
            error, 
            errors: this.errors,
            timestamp: Date.now() 
        });
        
        // Try to initialize what we can
        this.attemptPartialInit();
    }
    
    /**
     * Attempt partial initialization
     */
    attemptPartialInit() {
        this.log('Attempting partial initialization...');
        
        // Try to initialize at least the core map
        if (!this.components.maps && window.ThrillWikiMap) {
            try {
                const mapContainer = document.getElementById('map-container');
                if (mapContainer) {
                    this.components.maps = new ThrillWikiMap('map-container');
                    this.log('✓ Core map initialized in fallback mode');
                }
            } catch (error) {
                this.error('✗ Fallback map initialization failed:', error);
            }
        }
    }
    
    /**
     * Get component by name
     */
    getComponent(name) {
        return this.components[name] || null;
    }
    
    /**
     * Get all components
     */
    getAllComponents() {
        return { ...this.components };
    }
    
    /**
     * Check if integration is ready
     */
    isReady() {
        return this.initialized;
    }
    
    /**
     * Get initialization status
     */
    getStatus() {
        return {
            initialized: this.initialized,
            components: Object.keys(this.components),
            errors: this.errors,
            initTime: this.initStartTime ? performance.now() - this.initStartTime : null
        };
    }
    
    /**
     * Emit custom event
     */
    emitEvent(eventName, detail) {
        const event = new CustomEvent(eventName, { detail });
        document.dispatchEvent(event);
    }
    
    /**
     * Log performance metrics
     */
    logPerformance() {
        if (!this.options.enablePerformanceMonitoring) return;
        
        const initTime = performance.now() - this.initStartTime;
        const componentCount = Object.keys(this.components).length;
        
        this.log(`Performance: ${initTime.toFixed(2)}ms to initialize ${componentCount} components`);
        
        // Send to analytics if available
        if (typeof gtag !== 'undefined') {
            gtag('event', 'map_integration_performance', {
                event_category: 'performance',
                value: Math.round(initTime),
                custom_map: {
                    component_count: componentCount,
                    errors: this.errors.length
                }
            });
        }
    }
    
    /**
     * Logging methods
     */
    log(message, ...args) {
        if (this.options.enableLogging) {
            console.log(`[MapIntegration] ${message}`, ...args);
        }
    }
    
    warn(message, ...args) {
        if (this.options.enableLogging) {
            console.warn(`[MapIntegration] ${message}`, ...args);
        }
    }
    
    error(message, ...args) {
        if (this.options.enableLogging) {
            console.error(`[MapIntegration] ${message}`, ...args);
        }
    }
    
    /**
     * Destroy integration
     */
    destroy() {
        // Destroy all components
        Object.values(this.components).forEach(component => {
            if (component && typeof component.destroy === 'function') {
                try {
                    component.destroy();
                } catch (error) {
                    this.error('Error destroying component:', error);
                }
            }
        });
        
        this.components = {};
        this.initialized = false;
        this.log('Map integration destroyed');
    }
}

// Auto-initialize map integration
let mapIntegration;

document.addEventListener('DOMContentLoaded', function() {
    // Only initialize if we have map-related elements
    const hasMapElements = document.querySelector('#map-container, .map-container, [data-map], [data-roadtrip]');
    
    if (hasMapElements) {
        mapIntegration = new MapIntegration();
        window.mapIntegration = mapIntegration;
    }
});

// Global API for external access
window.ThrillWikiMaps = {
    getIntegration: () => mapIntegration,
    isReady: () => mapIntegration && mapIntegration.isReady(),
    getComponent: (name) => mapIntegration ? mapIntegration.getComponent(name) : null,
    getStatus: () => mapIntegration ? mapIntegration.getStatus() : { initialized: false }
};

// Export for module systems
if (typeof module !== 'undefined' && module.exports) {
    module.exports = MapIntegration;
} else {
    window.MapIntegration = MapIntegration;
}