import PhotoSwipeLightbox from 'https://dpangzi.com/library/photoswipe/photoswipe.esm.min.js';
import PhotoSwipe from 'https://dpangzi.com/library/photoswipe/photoswipe.esm.min.js';
import {dialog} from "./dialog.js";

export class Albums {
    constructor() {
        this.container = document.querySelector('.albums');
        if (!this.container) return;

        this.grid = this.container.querySelector('.albums__grid');
        this.loadingIndicator = this.container.querySelector('.albums__loading');
        this.noMoreIndicator = this.container.querySelector('.albums__no-more');
        // 统计栏中「第 X / Y 页」的文字节点所在的 span
        this.statPageEl = this.container.querySelector('.albums__stats span:last-child');
        
        // State
        this.pageIndex = parseInt(this.container.dataset.pageIndex) || 1;
        this.pageSize = parseInt(this.container.dataset.pageSize) || 20;
        this.totalPageCount = parseInt(this.container.dataset.totalPages) || 0;
        this.hasMore = this.container.dataset.hasMore === 'true';
        this.isLoading = false;
        
        this.items = []; // PhotoSwipe items
        
        this._isClosedByNavigation = false;
        this._isClosing = false;
        this.lightbox = null;

        // Bind functions
        this.onHashChange = this.onHashChange.bind(this);

        this.init();
    }

    init() {
        this.initMasonry();
        this.initInitialItems();
        this.initObserver();
        this.bindEvents();

        // Hash 导航
        window.addEventListener('hashchange', this.onHashChange);
        // 处理初始化时已存在的 Hash
        this.onHashChange();
    }

    initMasonry() {
        if (typeof Masonry === 'undefined') return;

        // 相册图片带有 width/height 属性,浏览器可自动推断宽高比,
        // Masonry 初始化时卡片高度已知,无需等待图片加载
        this._masonry = new Masonry(this.grid, {
            itemSelector: '.albums__item',        // 瀑布流条目选择器
            columnWidth: '.albums__grid-sizer',   // 列宽基准元素
            percentPosition: true,                // 百分比定位,适配响应式
            gutter: 16,                           // 卡片水平间距(px)
            transitionDuration: '0.3s',           // 卡片移动动画时长
        });

        // 排列完成后显示网格,触发淡入效果
        this.grid.classList.add('albums__grid--ready');
    }

    initInitialItems() {
        const cards = this.grid.querySelectorAll('.albums__card');
        cards.forEach(card => {
            this.addItemFromCard(card);
        });
    }

    addItemFromCard(card) {
        const img = card.querySelector('.albums__image');
        if (!img) return;

        const src = img.getAttribute('data-src-original') || img.src.replace('!albums', '');
        const id = img.getAttribute('data-id') || ''; // Get ID
        const width = parseInt(img.getAttribute('width')) || 0;
        const height = parseInt(img.getAttribute('height')) || 0;
        const desc = img.alt || '';

        this.items.push({
            id: id,
            src: src,
            w: width,
            h: height,
            alt: desc,
            // Reference to DOM element
            element: img
        });
        
        // Bind click to open PhotoSwipe
        // We use delegation on grid, so no individual binding needed here, 
        // but we need to know the index.
        card.dataset.index = (this.items.length - 1).toString();
        if (id) {
            card.dataset.id = id;
        }
    }

    initObserver() {
        if (!this.hasMore) {
            if (this.loadingIndicator) this.loadingIndicator.style.display = 'none';
            if (this.noMoreIndicator) this.noMoreIndicator.style.display = 'block';
            return;
        }

        const options = {
            root: null,
            rootMargin: '200px',
            threshold: 0.1
        };

        this.observer = new IntersectionObserver((entries) => {
            entries.forEach(entry => {
                if (entry.isIntersecting && !this.isLoading && this.hasMore) {
                    void this.loadMore();
                }
            });
        }, options);

        // Observe the loading indicator (which is at the bottom)
        if (this.loadingIndicator) {
            this.observer.observe(this.loadingIndicator);
        }
    }

    bindEvents() {
        // Event delegation for clicks
        this.grid.addEventListener('click', (e) => {
            const card = e.target.closest('.albums__card');
            const actionBtn = e.target.closest('.albums__action-btn');

            if (actionBtn) {
                // Handle action buttons (stop propagation to prevent opening gallery)
                e.stopPropagation();
                this.handleAction(actionBtn);
                return;
            }

            if (card) {
                const index = parseInt(card.dataset.index);
                if (!isNaN(index)) {
                    this.openGallery(index);
                }
            }
        });
    }

    parseHash() {
        const hash = window.location.hash;
        const match = hash.match(/#pid=([^&]+)/);
        if (match) {
            return match[1];
        }
        return null;
    }

    findItemIndexById(id) {
        if (!id) return -1;
        return this.items.findIndex(item => item.id === id);
    }

    onHashChange() {
        const id = this.parseHash();

        if (id !== null) {
            const index = this.findItemIndexById(id);
            // Check if index is valid
            if (index >= 0) {
                this.openGallery(index, true);
            }
        } else {
            // Hash cleared, close if open
            if (this.lightbox && !this._isClosing) {
                this._isClosedByNavigation = true;
                if (this.lightbox.pswp) {
                    this.lightbox.pswp.close();
                }
            }
        }
    }

    async loadMore() {
        if (this.isLoading || !this.hasMore) return;

        this.isLoading = true;
        
        try {
            const nextPage = this.pageIndex + 1;
            const url = `/pages/albums?pageIndex=${nextPage}&pageSize=${this.pageSize}`;
            
            const response = await fetch(url);
            if (!response.ok) {
                dialog.toast("网络响应错误", "error");
                return;
            }
            
            const data = await response.json();
            
            const items = data.items || data.Items || [];
            
            if (items.length > 0) {
                this.appendItems(items);
                this.pageIndex = nextPage;
                this.hasMore = nextPage < (data.totalPageCount || data.TotalPageCount);
                // 同步更新页头的页码显示
                this.updateStatPage();
            } else {
                this.hasMore = false;
            }

        } catch (error) {
            console.error('Error loading more albums:', error);
            // Optionally show error UI
        } finally {
            this.isLoading = false;
            this.updateUI();
        }
    }

    appendItems(items) {
        const fragment = document.createDocumentFragment();
        // 记录新增的 DOM 节点,用于通知 Masonry
        const newNodes = [];

        items.forEach(item => {
            // 统一属性名(兼容大小写)
            const id = item.Id || item.id;
            const url = item.AccessUrl || item.accessUrl;
            const desc = item.Description || item.description;
            const width = item.Width || item.width;
            const height = item.Height || item.height;
            const creator = item.Creator || item.creator;
            const uploadTime = item.UploadTime || item.uploadTime;
            const length = item.Length || item.length;

            const cardNode = this.createCardNode({
                id, url, desc, width, height, creator, uploadTime, length
            });

            fragment.appendChild(cardNode);
            newNodes.push(cardNode);

            // 同步追加到 PhotoSwipe 数据源
            this.items.push({
                id: id,
                src: url,
                w: width,
                h: height,
                alt: desc
            });

            // 为刚创建的卡片设置 PhotoSwipe 索引
            const card = cardNode.querySelector('.albums__card');
            card.dataset.index = (this.items.length - 1).toString();
            if (id) {
                card.dataset.id = id;
            }
        });

        this.grid.appendChild(fragment);

        // 通知 Masonry 有新卡片追加,触发重新布局
        if (this._masonry) {
            this._masonry.appended(newNodes);
        }
    }

    createCardNode(data) {
        const div = document.createElement('div');
        div.className = 'albums__item';
        
        // 格式化文件大小
        const sizeMB = (data.length / 1024 / 1024).toFixed(2);
        // 格式化上传日期
        const date = new Date(data.uploadTime).toLocaleDateString();
        const userName = (data.creator && (data.creator.Name || data.creator.name)) || 'Unknown';

        div.innerHTML = `
            <div class="albums__card">
                <div class="albums__image-wrapper">
                    <img class="albums__image is-loaded" 
                         src="${data.url}!albums" 
                         data-src-original="${data.url}"
                         data-id="${data.id || ''}"
                         alt="${this.escapeHtml(data.desc || '')}"
                         width="${data.width}" 
                         height="${data.height}" 
                         loading="lazy">
                    <div class="albums__overlay">
                        <div class="albums__actions">
                            <button class="albums__action-btn" data-action="download" data-url="${data.url}" title="下载">
                                <i class="fa fa-download"></i>
                            </button>
                            <button class="albums__action-btn" data-action="share" data-url="${data.url}" title="分享">
                                <i class="fa fa-share"></i>
                            </button>
                        </div>
                        <div class="albums__info">
                            <div class="albums__desc">${this.escapeHtml(data.desc || '')}</div>
                            <div class="albums__meta">
                                <div class="albums__meta-row">
                                    <span>${this.escapeHtml(userName)}</span>
                                    <span>${date}</span>
                                </div>
                                <div class="albums__meta-row">
                                    <span>${data.width} × ${data.height}</span>
                                    <span>${sizeMB} MB</span>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        `;
        return div;
    }

    updateUI() {
        if (!this.hasMore) {
            if (this.observer && this.loadingIndicator) {
                this.observer.unobserve(this.loadingIndicator);
            }
            if (this.loadingIndicator) this.loadingIndicator.style.display = 'none';
            if (this.noMoreIndicator) this.noMoreIndicator.style.display = 'block';
        }
    }

    /** 更新页头「第 X / Y 页」文字 */
    updateStatPage() {
        if (this.statPageEl) {
            this.statPageEl.textContent = `第 ${this.pageIndex} / ${this.totalPageCount} 页`;
        }
    }

    openGallery(index, fromHash = false) {
        if (this.lightbox) {
            // If already open, just update index
            if (this.lightbox.pswp) {
                this.lightbox.pswp.goTo(index);
            }
            return;
        }

        this._isClosing = false;

        const lightbox = new PhotoSwipeLightbox({
            dataSource: this.items,
            pswpModule: PhotoSwipe,
            index: index,
            bgOpacity: 0.9,
            showHideAnimationType: 'zoom'
        });
        
        this.lightbox = lightbox;

        lightbox.on('change', () => {
            const pswp = lightbox.pswp;
            if (pswp) {
                const currItem = pswp.currSlide.data;
                if (currItem && currItem.id) {
                    const newHash = `#pid=${currItem.id}`;
                    if (window.location.hash !== newHash) {
                        history.replaceState(null, null, newHash);
                    }
                }
            }
        });

        lightbox.on('close', () => {
            this._isClosing = true;
            // If hash is present and we are not closing by navigation (back button),
            // then we should go back to clear the hash.
            if (!this._isClosedByNavigation && this.parseHash() !== null) {
                history.back();
            }
            this.lightbox = null;
            this._isClosedByNavigation = false;
        });

        // If not opened from hash, push the initial state
        if (!fromHash) {
            const item = this.items[index];
            if (item && item.id) {
                history.pushState(null, '', `#pid=${item.id}`);
            }
        }
        
        lightbox.init();
    }

    handleAction(btn) {
        const action = btn.dataset.action;
        const url = btn.dataset.url;
        
        if (action === 'download') {
            this.downloadImage(url);
        } else if (action === 'share') {
            this.shareImage(url);
        }
    }
    
    downloadImage(url) {
        const link = document.createElement('a');
        link.href = url;
        link.download = ''; // Browser handles filename
        link.target = '_blank';
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
    }
    
    shareImage(url) {
        if (navigator.share) {
            navigator.share({
                title: '分享图片',
                url: url
            }).catch(console.error);
        } else {
            // Fallback to clipboard
            navigator.clipboard.writeText(url).then(() => {
                alert('图片链接已复制到剪贴板');
            }).catch(() => {
                prompt('复制链接:', url);
            });
        }
    }

    escapeHtml(text) {
        if (!text) return '';
        return text
            .replace(/&/g, "&amp;")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;")
            .replace(/"/g, "&quot;")
            .replace(/'/g, "&#039;");
    }
}
评论加载中...