/**
 * YITAO-REN GALLERY 图片懒加载脚本
 * 优化图片加载性能，提升用户体验
 */

class LazyLoader {
    constructor(options = {}) {
        this.options = {
            root: null,
            rootMargin: '50px 0px',
            threshold: 0.1,
            placeholder: 'data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"%3E%3Crect width="100" height="100" fill="%231e293b"/%3E%3C/svg%3E',
            loadingClass: 'lazy-loading',
            loadedClass: 'lazy-loaded',
            errorClass: 'lazy-error',
            ...options
        };

        this.observer = null;
        this.images = new Map();
        this.init();
    }

    init() {
        // 创建 IntersectionObserver 实例
        this.observer = new IntersectionObserver(
            this.handleIntersection.bind(this),
            this.options
        );

        // 查找所有需要懒加载的图片
        this.findImages();
        this.setupEventListeners();
    }

    findImages() {
        const selectors = [
            'img[data-src]',
            'img[data-srcset]',
            'source[data-srcset]',
            'iframe[data-src]'
        ].join(',');

        document.querySelectorAll(selectors).forEach(element => {
            this.observe(element);
        });
    }

    observe(element) {
        // 设置占位符
        if (element.tagName === 'IMG' && !element.src) {
            element.src = this.options.placeholder;
            element.classList.add(this.options.loadingClass);
        }

        // 添加到观察列表
        this.images.set(element, {
            src: element.dataset.src,
            srcset: element.dataset.srcset,
            loaded: false
        });

        // 开始观察
        this.observer.observe(element);
    }

    handleIntersection(entries) {
        entries.forEach(entry => {
            if (entry.isIntersecting) {
                this.loadImage(entry.target);
                this.observer.unobserve(entry.target);
            }
        });
    }

    loadImage(element) {
        const imageData = this.images.get(element);
        if (!imageData || imageData.loaded) return;

        imageData.loaded = true;

        // 创建新的 Image 对象预加载
        const img = new Image();

        img.onload = () => {
            this.setImageSource(element, imageData);
            this.handleLoadSuccess(element);
        };

        img.onerror = () => {
            this.handleLoadError(element);
        };

        // 开始加载
        img.src = imageData.src || imageData.srcset || '';
    }

    setImageSource(element, imageData) {
        if (imageData.src && element.tagName === 'IMG') {
            element.src = imageData.src;
        }

        if (imageData.srcset) {
            if (element.tagName === 'IMG') {
                element.srcset = imageData.srcset;
            } else if (element.tagName === 'SOURCE') {
                element.srcset = imageData.srcset;
            }
        }

        // 移除 data 属性以节省内存
        delete element.dataset.src;
        delete element.dataset.srcset;
    }

    handleLoadSuccess(element) {
        element.classList.remove(this.options.loadingClass);
        element.classList.add(this.options.loadedClass);

        // 触发自定义事件
        const event = new CustomEvent('lazyload:loaded', {
            detail: { element }
        });
        element.dispatchEvent(event);

        // 添加淡入动画
        this.animateFadeIn(element);
    }

    handleLoadError(element) {
        element.classList.remove(this.options.loadingClass);
        element.classList.add(this.options.errorClass);

        // 设置错误占位符
        if (element.tagName === 'IMG') {
            element.src = 'data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"%3E%3Crect width="100" height="100" fill="%231e293b"/%3E%3Ctext x="50" y="50" text-anchor="middle" dy=".3em" fill="%239ca3af" font-size="8"%3E加载失败%3C/text%3E%3C/svg%3E';
        }

        // 触发自定义事件
        const event = new CustomEvent('lazyload:error', {
            detail: { element }
        });
        element.dispatchEvent(event);
    }

    animateFadeIn(element) {
        element.style.opacity = '0';
        element.style.transition = 'opacity 0.5s ease';

        // 使用 requestAnimationFrame 确保样式已应用
        requestAnimationFrame(() => {
            element.style.opacity = '1';

            // 动画完成后清理样式
            setTimeout(() => {
                element.style.transition = '';
                element.style.opacity = '';
            }, 500);
        });
    }

    setupEventListeners() {
        // 监听动态添加的图片
        const observer = new MutationObserver(mutations => {
            mutations.forEach(mutation => {
                mutation.addedNodes.forEach(node => {
                    if (node.nodeType === 1) { // Element node
                        if (node.matches && node.matches('img[data-src], img[data-srcset], source[data-srcset], iframe[data-src]')) {
                            this.observe(node);
                        }

                        // 检查子元素
                        node.querySelectorAll?.('img[data-src], img[data-srcset], source[data-srcset], iframe[data-src]').forEach(element => {
                            this.observe(element);
                        });
                    }
                });
            });
        });

        observer.observe(document.body, {
            childList: true,
            subtree: true
        });

        // 窗口 resize 时重新检查可见性
        let resizeTimer;
        window.addEventListener('resize', () => {
            clearTimeout(resizeTimer);
            resizeTimer = setTimeout(() => {
                this.checkVisibleImages();
            }, 250);
        });

        // 页面可见性变化时重新检查
        document.addEventListener('visibilitychange', () => {
            if (!document.hidden) {
                this.checkVisibleImages();
            }
        });
    }

    checkVisibleImages() {
        // 重新检查所有未加载的图片
        this.images.forEach((data, element) => {
            if (!data.loaded) {
                const rect = element.getBoundingClientRect();
                const isVisible = (
                    rect.top <= window.innerHeight + 100 &&
                    rect.bottom >= -100 &&
                    rect.left <= window.innerWidth + 100 &&
                    rect.right >= -100
                );

                if (isVisible) {
                    this.loadImage(element);
                    this.observer.unobserve(element);
                }
            }
        });
    }

    destroy() {
        if (this.observer) {
            this.observer.disconnect();
            this.observer = null;
        }

        this.images.clear();
    }
}

// 自动初始化
document.addEventListener('DOMContentLoaded', () => {
    window.lazyLoader = new LazyLoader();

    // 暴露全局方法
    window.lazyLoadImages = () => {
        window.lazyLoader?.checkVisibleImages();
    };

    // 预加载关键图片
    const criticalImages = document.querySelectorAll('.critical-image[data-src]');
    criticalImages.forEach(img => {
        const src = img.dataset.src;
        if (src) {
            const preloadLink = document.createElement('link');
            preloadLink.rel = 'preload';
            preloadLink.as = 'image';
            preloadLink.href = src;
            document.head.appendChild(preloadLink);
        }
    });
});

// 导出供模块化使用
if (typeof module !== 'undefined' && module.exports) {
    module.exports = LazyLoader;
}

/**
 * 使用示例：
 *
 * 1. 基本用法：
 * <img data-src="/path/to/image.jpg" class="lazy-image">
 *
 * 2. 响应式图片：
 * <img data-src="/small.jpg" data-srcset="/small.jpg 480w, /medium.jpg 768w, /large.jpg 1200w" sizes="(max-width: 600px) 480px, (max-width: 1200px) 768px, 1200px">
 *
 * 3. 背景图片懒加载：
 * <div data-bg="/path/to/image.jpg" class="lazy-bg"></div>
 *
 * 4. 手动触发加载：
 * window.lazyLoadImages();
 */