/**
 * Elementor PDF Smart Viewer JavaScript
 *
 * @package ElementorPDFSmartViewer
 * @version 1.0.4
 */

(function($) {
    'use strict';

    class PDFSmartViewer {
        constructor(container) {
            this.container = container;
            this.canvas = container.querySelector('.epsv-canvas');
            
            // Check if canvas exists and get context
            if (!this.canvas) {
                console.error('Canvas element not found');
                return;
            }
            
            this.ctx = this.canvas.getContext('2d');
            if (!this.ctx) {
                console.error('Canvas 2D context not supported');
                return;
            }
            
            this.pdfUrl = container.getAttribute('data-pdf-url');
            this.widgetId = container.getAttribute('data-widget-id');
            this.initialZoom = parseFloat(container.getAttribute('data-initial-zoom')) || 1;
            
            // Control visibility settings
            this.showZoomControls = container.getAttribute('data-show-zoom') === 'true';
            this.showFullscreen = container.getAttribute('data-show-fullscreen') === 'true';
            this.showDownload = container.getAttribute('data-show-download') === 'true';
            this.showPrint = container.getAttribute('data-show-print') === 'true';
            this.showPageInfo = container.getAttribute('data-show-page-info') === 'true';
            
            // State variables
            this.pdfDoc = null;
            this.currentPage = 1;
            this.currentZoom = this.initialZoom;
            this.isRendering = false;
            this.pendingPage = null;
            this.isFullscreen = false;
            this.currentRenderTask = null;
            this.hasRenderedFirstPage = false;
            
            // DOM elements
            this.loadingEl = container.querySelector('.epsv-loading');
            this.errorEl = container.querySelector('.epsv-error');
            this.zoomLevelEl = container.querySelector('.epsv-zoom-level');
            this.pageCurrentEl = container.querySelector('.epsv-page-current');
            this.pageTotalEl = container.querySelector('.epsv-page-total');
            
            // Buttons
            this.prevBtn = container.querySelector('.epsv-prev');
            this.nextBtn = container.querySelector('.epsv-next');
            this.zoomInBtn = container.querySelector('.epsv-zoom-in');
            this.zoomOutBtn = container.querySelector('.epsv-zoom-out');
            this.fullscreenBtn = container.querySelector('.epsv-fullscreen');
            this.downloadBtn = container.querySelector('.epsv-download');
            this.printBtn = container.querySelector('.epsv-print');
            
            this.init();
        }
        
        init() {
            if (!this.canvas || !this.ctx) {
                this.showError('Canvas not available');
                return;
            }
            
            if (!this.pdfUrl) {
                this.showError('No PDF URL provided');
                return;
            }
            
            // Pre-hide canvas for first page to prevent any blink
            this.canvas.style.visibility = 'hidden';
            this.canvas.style.opacity = '0';
            
            this.bindEvents();
            this.loadPDF();
        }
        
        bindEvents() {
            // Navigation events
            if (this.prevBtn) {
                this.prevBtn.addEventListener('click', (e) => {
                    e.preventDefault();
                    this.previousPage();
                });
            }
            
            if (this.nextBtn) {
                this.nextBtn.addEventListener('click', (e) => {
                    e.preventDefault();
                    this.nextPage();
                });
            }
            
            // Zoom events
            if (this.zoomInBtn) {
                this.zoomInBtn.addEventListener('click', (e) => {
                    e.preventDefault();
                    this.zoomIn();
                });
            }
            
            if (this.zoomOutBtn) {
                this.zoomOutBtn.addEventListener('click', (e) => {
                    e.preventDefault();
                    this.zoomOut();
                });
            }
            
            // Fullscreen events
            if (this.fullscreenBtn) {
                this.fullscreenBtn.addEventListener('click', (e) => {
                    e.preventDefault();
                    this.toggleFullscreen();
                });
            }
            
            // Download events
            if (this.downloadBtn) {
                this.downloadBtn.addEventListener('click', (e) => {
                    e.preventDefault();
                    this.downloadPDF();
                });
            }
            
            // Print events
            if (this.printBtn) {
                this.printBtn.addEventListener('click', (e) => {
                    e.preventDefault();
                    this.printPDF();
                });
            }
            
            // Keyboard events
            document.addEventListener('keydown', (e) => {
                if (!this.container.contains(document.activeElement) && !this.isFullscreen) {
                    return;
                }
                
                switch(e.key) {
                    case 'ArrowLeft':
                        e.preventDefault();
                        this.previousPage();
                        break;
                    case 'ArrowRight':
                        e.preventDefault();
                        this.nextPage();
                        break;
                    case '+':
                    case '=':
                        e.preventDefault();
                        this.zoomIn();
                        break;
                    case '-':
                        e.preventDefault();
                        this.zoomOut();
                        break;
                    case 'f':
                    case 'F':
                        e.preventDefault();
                        this.toggleFullscreen();
                        break;
                    case 'Escape':
                        if (this.isFullscreen) {
                            e.preventDefault();
                            this.exitFullscreen();
                        }
                        break;
                }
            });
            
            // Resize events
            this.debouncedResize = this.debounce(() => {
                this.renderCurrentPage();
            }, 250);
            
            window.addEventListener('resize', this.debouncedResize);
            
            // Fullscreen change events
            document.addEventListener('fullscreenchange', () => {
                this.handleFullscreenChange();
            });
        }
        
        loadPDF() {
            this.showLoading();
            
            // Reset first page rendering flag
            this.hasRenderedFirstPage = false;
            
            // Ensure canvas is initially visible (will be hidden during first page render if needed)
            this.canvas.style.visibility = 'visible';
            this.canvas.style.opacity = '1';
            
            // Pre-initialize canvas context for incognito mode fix
            this.preInitializeCanvas();
            
            // Set PDF.js worker path
            if (typeof pdfjsLib !== 'undefined') {
                pdfjsLib.GlobalWorkerOptions.workerSrc = pdfsmvif_ajax.plugin_url + 'assets/js/pdf.worker.min.js';
                
                // Check if it's a remote URL that might have CORS issues
                const isRemoteUrl = this.isRemoteUrl(this.pdfUrl);
                
                if (isRemoteUrl) {
                    this.loadPDFWithFallback();
                } else {
                    this.loadPDFDirect();
                }
            } else {
                this.showError('PDF.js library not loaded');
            }
        }
        
        preInitializeCanvas() {
            // Pre-initialize canvas context to prevent incognito mode issues
            if (this.canvas && this.ctx) {
                try {
                    // Force canvas context to be ready
                    this.canvas.width = 1;
                    this.canvas.height = 1;
                    this.ctx.clearRect(0, 0, 1, 1);
                    
                    // Test context operations
                    this.ctx.save();
                    this.ctx.restore();
                    
                    // Reset canvas
                    this.canvas.width = 0;
                    this.canvas.height = 0;
                } catch (e) {
                    console.warn('Canvas pre-initialization failed:', e);
                }
            }
        }
        
        isRemoteUrl(url) {
            try {
                const urlObj = new URL(url);
                const currentOrigin = window.location.origin;
                return urlObj.origin !== currentOrigin;
            } catch (e) {
                return false;
            }
        }
        
        loadPDFDirect() {
            pdfjsLib.getDocument(this.pdfUrl).promise
                .then((pdf) => {
                    this.pdfDoc = pdf;
                    this.hideLoading();
                    this.updatePageTotal();
                    
                    // Small delay to ensure everything is ready for first render in incognito mode
                    setTimeout(() => {
                        this.renderCurrentPage();
                        this.updateControls();
                    }, 50);
                })
                .catch((error) => {
                    console.error('Error loading PDF directly:', error);
                    this.showError('Failed to load PDF. Please check the URL or file.');
                });
        }
        
        loadPDFWithFallback() {
            // For remote URLs, try direct loading first (some servers allow it)
            
            pdfjsLib.getDocument(this.pdfUrl).promise
                .then((pdf) => {
                    this.pdfDoc = pdf;
                    this.hideLoading();
                    this.updatePageTotal();
                    
                    // Small delay to ensure everything is ready for first render in incognito mode
                    setTimeout(() => {
                        this.renderCurrentPage();
                        this.updateControls();
                    }, 50);
                })
                .catch((directError) => {
                    console.error('Error loading PDF directly:', directError);
                    
                    // If direct loading fails, try the proxy
                    const proxyUrl = this.getProxyUrl(this.pdfUrl);
                    
                    pdfjsLib.getDocument(proxyUrl).promise
                        .then((pdf) => {
                            this.pdfDoc = pdf;
                            this.hideLoading();
                            this.updatePageTotal();
                            
                            // Small delay to ensure everything is ready for first render in incognito mode
                            setTimeout(() => {
                                this.renderCurrentPage();
                                this.updateControls();
                            }, 50);
                        })
                        .catch((proxyError) => {
                            console.error('Error loading PDF via proxy:', proxyError);
                            
                            // If both PDF.js methods fail, try iframe fallback
                            this.loadPDFWithIframe();
                        });
                });
        }

        loadPDFWithIframe() {
            // Hide the canvas and show download link instead
            if (this.canvas) {
                this.canvas.style.display = 'none';
            }
            
            // Create a download link for external PDFs
            const downloadContainer = document.createElement('div');
            downloadContainer.className = 'epsv-external-pdf';
            downloadContainer.style.cssText = `
                text-align: center;
                padding: 40px 20px;
                background: #f8f9fa;
                border: 2px dashed #dee2e6;
                border-radius: 8px;
                margin: 20px 0;
            `;
            
            const icon = document.createElement('div');
            icon.innerHTML = '📄';
            icon.style.cssText = `
                font-size: 48px;
                margin-bottom: 20px;
            `;
            
            const title = document.createElement('h3');
            title.textContent = 'External PDF Document';
            title.style.cssText = `
                margin: 0 0 15px 0;
                color: #495057;
                font-size: 18px;
            `;
            
            const description = document.createElement('p');
            description.textContent = 'This PDF is hosted on an external server. Due to security restrictions, it cannot be displayed directly in the viewer.';
            description.style.cssText = `
                margin: 0 0 20px 0;
                color: #6c757d;
                line-height: 1.5;
            `;
            
            const downloadBtn = document.createElement('a');
            downloadBtn.href = this.pdfUrl;
            downloadBtn.target = '_blank';
            downloadBtn.textContent = 'Open PDF in New Tab';
            downloadBtn.className = 'button button-primary';
            downloadBtn.style.cssText = `
                display: inline-block;
                padding: 12px 24px;
                background: #0073aa;
                color: white;
                text-decoration: none;
                border-radius: 4px;
                font-weight: 500;
                transition: background 0.3s;
            `;
            
            downloadBtn.addEventListener('mouseenter', () => {
                downloadBtn.style.background = '#005a87';
            });
            
            downloadBtn.addEventListener('mouseleave', () => {
                downloadBtn.style.background = '#0073aa';
            });
            
            // Add elements to container
            downloadContainer.appendChild(icon);
            downloadContainer.appendChild(title);
            downloadContainer.appendChild(description);
            downloadContainer.appendChild(downloadBtn);
            
            // Add to the viewer container
            const viewerContainer = this.canvas.parentElement;
            viewerContainer.appendChild(downloadContainer);
            
            // Hide loading
            this.hideLoading();
            
            // Hide controls since we're showing a download link
            if (this.container.querySelector('.epsv-controls')) {
                this.container.querySelector('.epsv-controls').style.display = 'none';
            }
        }

        getProxyUrl(pdfUrl) {
            // Create proxy URL with nonce for security
            const proxyUrl = new URL(pdfsmvif_ajax.ajax_url);
            proxyUrl.searchParams.set('action', 'pdfsmvif_proxy_pdf');
            proxyUrl.searchParams.set('url', encodeURIComponent(pdfUrl));
            proxyUrl.searchParams.set('nonce', pdfsmvif_ajax.proxy_nonce);
            return proxyUrl.toString();
        }
        
        renderCurrentPage() {
            if (!this.pdfDoc) return;

            // If a render is in progress or being cancelled, queue the latest request
            if (this.isRendering || this.currentRenderTask) {
                this.pendingPage = this.currentPage;
                this.pendingZoom = this.currentZoom;
                // If a render task exists, cancel it (if not already cancelling)
                if (this.currentRenderTask && !this.currentRenderTask._cancelling) {
                    this.currentRenderTask._cancelling = true;
                    this.currentRenderTask.cancel();
                }
                return;
            }

            this.isRendering = true;
            this.pendingPage = null;
            this.pendingZoom = null;

            // IMMEDIATELY hide canvas for first page to prevent any blink
            if (this.currentPage === 1 && !this.hasRenderedFirstPage) {
                this.canvas.style.visibility = 'hidden';
                this.canvas.style.opacity = '0';
            }

            this.pdfDoc.getPage(this.currentPage).then((page) => {
                const containerWidth = this.canvas.parentElement.clientWidth;
                const viewport = page.getViewport({ scale: 1 });
                const scale = (containerWidth / viewport.width) * this.currentZoom;
                const scaledViewport = page.getViewport({ scale });

                // Comprehensive fix for incognito mode upside-down first page issue
                if (this.currentPage === 1 && !this.hasRenderedFirstPage) {
                    this.renderFirstPageWithFix(page, scaledViewport);
                } else {
                    this.renderPageNormally(page, scaledViewport);
                }
            }).catch((error) => {
                if (typeof console !== 'undefined' && console.error) {
                    console.error('Error getting page:', error);
                }
                this.isRendering = false;
                this.currentRenderTask = null;
                this.showError('Failed to load page');
            });
        }
        
        renderFirstPageWithFix(page, scaledViewport) {
            // Hide canvas during first page rendering to prevent blink
            this.canvas.style.visibility = 'hidden';
            
            // Safety timeout to ensure canvas becomes visible even if something goes wrong
            const safetyTimeout = setTimeout(() => {
                this.canvas.style.visibility = 'visible';
                this.canvas.style.opacity = '1';
                console.warn('Safety timeout: Canvas made visible after 3 seconds');
            }, 3000);
            
            // Multiple strategies to fix incognito mode upside-down issue
            const attemptRender = (attempt = 0) => {
                if (attempt >= 3) {
                    // Final fallback - render normally but keep hidden until ready
                    this.renderPageNormallyWithVisibilityControl(page, scaledViewport);
                    return;
                }
                
                // Strategy 1: Force canvas reset and context recreation
                this.canvas.width = scaledViewport.width;
                this.canvas.height = scaledViewport.height;
                this.ctx = this.canvas.getContext('2d');
                
                // Strategy 2: Clear canvas completely
                this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
                
                // Strategy 3: Force a small delay to ensure context is ready
                setTimeout(() => {
                    try {
                        // Strategy 4: Test context with a simple operation
                        this.ctx.save();
                        this.ctx.restore();
                        
                        // Strategy 5: Render with explicit viewport settings
                        const renderContext = {
                            canvasContext: this.ctx,
                            viewport: scaledViewport,
                            transform: null // Force PDF.js to use default transform
                        };
                        
                        this.currentRenderTask = page.render(renderContext);
                        
                        this.currentRenderTask.promise.then(() => {
                            // Clear safety timeout
                            clearTimeout(safetyTimeout);
                            
                            // Show canvas only after successful render
                            this.canvas.style.visibility = 'visible';
                            this.canvas.style.opacity = '1';
                            
                            this.isRendering = false;
                            this.currentRenderTask = null;
                            this.hasRenderedFirstPage = true;
                            this.updatePageInfo();
                            this.updateControls();
                            
                            // If a render is pending, start it now
                            if (this.pendingPage !== null) {
                                this.currentPage = this.pendingPage;
                                this.currentZoom = this.pendingZoom || this.currentZoom;
                                this.pendingPage = null;
                                this.pendingZoom = null;
                                this.renderCurrentPage();
                            }
                        }).catch((error) => {
                            // Clear safety timeout
                            clearTimeout(safetyTimeout);
                            
                            if (error && error.name !== 'RenderingCancelled') {
                                console.error('First page render error, retrying:', error);
                                // Retry with next attempt
                                attemptRender(attempt + 1);
                            } else {
                                this.isRendering = false;
                                this.currentRenderTask = null;
                                // Show canvas even on cancellation
                                this.canvas.style.visibility = 'visible';
                                this.canvas.style.opacity = '1';
                            }
                        });
                        
                    } catch (e) {
                        console.error('Context error, retrying:', e);
                        attemptRender(attempt + 1);
                    }
                }, 50 + (attempt * 25)); // Increasing delay with each attempt
            };
            
            attemptRender();
        }
        
        renderPageNormallyWithVisibilityControl(page, scaledViewport) {
            // Safety timeout to ensure canvas becomes visible
            const safetyTimeout = setTimeout(() => {
                this.canvas.style.visibility = 'visible';
                this.canvas.style.opacity = '1';
                console.warn('Safety timeout: Canvas made visible after 2 seconds (fallback)');
            }, 2000);
            
            // Set canvas dimensions
            this.canvas.width = scaledViewport.width;
            this.canvas.height = scaledViewport.height;
            
            // Clear the canvas
            this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
            
            // Render the page
            const renderContext = {
                canvasContext: this.ctx,
                viewport: scaledViewport
            };

            this.currentRenderTask = page.render(renderContext);

            this.currentRenderTask.promise.then(() => {
                // Clear safety timeout
                clearTimeout(safetyTimeout);
                
                // Show canvas after successful render
                this.canvas.style.visibility = 'visible';
                this.canvas.style.opacity = '1';
                
                this.isRendering = false;
                this.currentRenderTask = null;
                this.hasRenderedFirstPage = true;
                this.updatePageInfo();
                this.updateControls();
                
                // If a render is pending, start it now
                if (this.pendingPage !== null) {
                    this.currentPage = this.pendingPage;
                    this.currentZoom = this.pendingZoom || this.currentZoom;
                    this.pendingPage = null;
                    this.pendingZoom = null;
                    this.renderCurrentPage();
                }
            }).catch((error) => {
                // Clear safety timeout
                clearTimeout(safetyTimeout);
                
                // Show canvas even on error
                this.canvas.style.visibility = 'visible';
                this.canvas.style.opacity = '1';
                
                this.isRendering = false;
                this.currentRenderTask = null;
                // Only show error if it's not a cancellation
                if (error && error.name !== 'RenderingCancelled') {
                    if (typeof console !== 'undefined' && console.error) {
                        console.error('Error rendering page:', error);
                    }
                    this.showError('Failed to render page');
                }
                // If a render is pending, start it now
                if (this.pendingPage !== null) {
                    this.currentPage = this.pendingPage;
                    this.currentZoom = this.pendingZoom || this.currentZoom;
                    this.pendingPage = null;
                    this.pendingZoom = null;
                    this.renderCurrentPage();
                }
            });
        }
        
        renderPageNormally(page, scaledViewport) {
            // Ensure canvas is visible for subsequent pages
            this.canvas.style.visibility = 'visible';
            
            // Set canvas dimensions
            this.canvas.width = scaledViewport.width;
            this.canvas.height = scaledViewport.height;
            
            // Clear the canvas
            this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
            
            // Render the page
            const renderContext = {
                canvasContext: this.ctx,
                viewport: scaledViewport
            };

            this.currentRenderTask = page.render(renderContext);

            this.currentRenderTask.promise.then(() => {
                this.isRendering = false;
                this.currentRenderTask = null;
                this.updatePageInfo();
                this.updateControls();
                
                // Mark that we've rendered the first page successfully
                if (this.currentPage === 1) {
                    this.hasRenderedFirstPage = true;
                }

                // If a render is pending, start it now
                if (this.pendingPage !== null) {
                    this.currentPage = this.pendingPage;
                    this.currentZoom = this.pendingZoom || this.currentZoom;
                    this.pendingPage = null;
                    this.pendingZoom = null;
                    this.renderCurrentPage();
                }
            }).catch((error) => {
                this.isRendering = false;
                this.currentRenderTask = null;
                // Only show error if it's not a cancellation
                if (error && error.name !== 'RenderingCancelled') {
                    if (typeof console !== 'undefined' && console.error) {
                        console.error('Error rendering page:', error);
                    }
                    this.showError('Failed to render page');
                }
                // If a render is pending, start it now
                if (this.pendingPage !== null) {
                    this.currentPage = this.pendingPage;
                    this.currentZoom = this.pendingZoom || this.currentZoom;
                    this.pendingPage = null;
                    this.pendingZoom = null;
                    this.renderCurrentPage();
                }
            });
        }
        
        previousPage() {
            if (this.currentPage <= 1) return;
            this.currentPage--;
            this.renderCurrentPage();
        }
        
        nextPage() {
            if (!this.pdfDoc || this.currentPage >= this.pdfDoc.numPages) return;
            this.currentPage++;
            this.renderCurrentPage();
        }
        
        zoomIn() {
            this.currentZoom = Math.min(this.currentZoom * 1.25, 3);
            this.updateZoomLevel();
            this.renderCurrentPage();
        }
        
        zoomOut() {
            this.currentZoom = Math.max(this.currentZoom / 1.25, 0.25);
            this.updateZoomLevel();
            this.renderCurrentPage();
        }
        
        toggleFullscreen() {
            if (this.isFullscreen) {
                this.exitFullscreen();
            } else {
                this.enterFullscreen();
            }
        }
        
        enterFullscreen() {
            if (this.container.requestFullscreen) {
                this.container.requestFullscreen();
            } else if (this.container.webkitRequestFullscreen) {
                this.container.webkitRequestFullscreen();
            } else if (this.container.msRequestFullscreen) {
                this.container.msRequestFullscreen();
            }
        }
        
        exitFullscreen() {
            if (document.exitFullscreen) {
                document.exitFullscreen();
            } else if (document.webkitExitFullscreen) {
                document.webkitExitFullscreen();
            } else if (document.msExitFullscreen) {
                document.msExitFullscreen();
            }
        }
        
        handleFullscreenChange() {
            this.isFullscreen = !!document.fullscreenElement;
            this.container.classList.toggle('epsv-fullscreen', this.isFullscreen);
            
            if (this.isFullscreen) {
                this.renderCurrentPage();
            }
        }
        
        downloadPDF() {
            const link = document.createElement('a');
            link.href = this.pdfUrl;
            link.download = this.getFileNameFromUrl(this.pdfUrl);
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
        }
        
        printPDF() {
            const printWindow = window.open(this.pdfUrl, '_blank');
            if (printWindow) {
                printWindow.onload = function() {
                    printWindow.print();
                };
            }
        }
        
        updatePageInfo() {
            if (this.pageCurrentEl) {
                this.pageCurrentEl.textContent = this.currentPage;
            }
        }
        
        updatePageTotal() {
            if (this.pageTotalEl && this.pdfDoc) {
                this.pageTotalEl.textContent = this.pdfDoc.numPages;
            }
        }
        
        updateZoomLevel() {
            if (this.zoomLevelEl) {
                this.zoomLevelEl.textContent = Math.round(this.currentZoom * 100) + '%';
            }
        }
        
        updateControls() {
            // Update navigation buttons
            if (this.prevBtn) {
                this.prevBtn.disabled = this.currentPage <= 1;
            }
            
            if (this.nextBtn) {
                this.nextBtn.disabled = !this.pdfDoc || this.currentPage >= this.pdfDoc.numPages;
            }
            
            // Update zoom buttons
            if (this.zoomInBtn) {
                this.zoomInBtn.disabled = this.currentZoom >= 3;
            }
            
            if (this.zoomOutBtn) {
                this.zoomOutBtn.disabled = this.currentZoom <= 0.25;
            }
        }
        
        showLoading() {
            if (this.loadingEl) {
                this.loadingEl.style.display = 'block';
            }
            if (this.errorEl) {
                this.errorEl.style.display = 'none';
            }
        }
        
        hideLoading() {
            if (this.loadingEl) {
                this.loadingEl.style.display = 'none';
            }
        }
        
        showError(message) {
            this.hideLoading();
            if (this.errorEl) {
                const span = this.errorEl.querySelector('span');
                if (span) {
                    span.textContent = message;
                }
                this.errorEl.style.display = 'block';
            }
        }
        
        getFileNameFromUrl(url) {
            try {
                const urlObj = new URL(url);
                const pathname = urlObj.pathname;
                const filename = pathname.substring(pathname.lastIndexOf('/') + 1);
                return filename || 'document.pdf';
            } catch (e) {
                return 'document.pdf';
            }
        }
        
        debounce(func, wait) {
            let timeout;
            return function executedFunction(...args) {
                clearTimeout(timeout);
                timeout = setTimeout(() => {
                    func.apply(this, args);
                }, wait);
            };
        }
        
        destroy() {
            // Cancel any ongoing render task
            if (this.currentRenderTask) {
                this.currentRenderTask.cancel();
                this.currentRenderTask = null;
            }
            
            // Remove event listeners
            if (this.debouncedResize) {
                window.removeEventListener('resize', this.debouncedResize);
            }
            
            // Clear any pending operations
            this.isRendering = false;
            this.pendingPage = null;
        }
    }
    
    // Initialize viewers when DOM is ready
    $(document).ready(function() {
        const containers = document.querySelectorAll('.epsv-container');
        containers.forEach(container => {
            new PDFSmartViewer(container);
        });
    });
    
    // Re-initialize on Elementor frontend init
    $(window).on('elementor/frontend/init', function() {
        elementorFrontend.hooks.addAction('frontend/element_ready/global', function($scope) {
            const containers = $scope.find('.epsv-container');
            containers.each(function() {
                if (!this.epsvInstance) {
                    this.epsvInstance = new PDFSmartViewer(this);
                }
            });
        });
    });
    
})(jQuery); 