Source: view_all_card.js

import { importCardsList } from './editor-page.js';
import { handleFiles,  } from './homepage.js';

/**
 * Render a preview of a card on a canvas with scaling applied.
 * @param {HTMLCanvasElement} canvas - The canvas to render on.
 * @param {Object} data - The card data object.
 * @param {number} width - Target width for rendering.
 * @param {number} height - Target height for rendering.
 */
export function renderScaledPreview(canvas, data, width, height) {
    const ctx = canvas.getContext('2d');
    if (!ctx) {
        console.error('Failed to get 2D context for canvas');
        return;
    }

    canvas.width = width;
    canvas.height = height;

    const originalWidth = data.width || 1080;
    const originalHeight = data.height || 600;

    const scaleX = width / originalWidth;
    const scaleY = height / originalHeight;

    ctx.setTransform(scaleX, 0, 0, scaleY, 0, 0);
    ctx.clearRect(0, 0, originalWidth, originalHeight);

    if (!data.objects || !data.objects.length) {
        ctx.fillStyle = 'black';
        ctx.font = '20px Arial';
        ctx.fillText('No Content', 50, 50);
        return;
    }

    for (const obj of data.objects) {
        const d = obj.data;
        switch (obj.type) {
            case 'textbox':
                ctx.font = `${d.bold ? 'bold ' : ''}${d.italics ? 'italic ' : ''}${d.size}px ${d.style}`;
                ctx.fillStyle = `rgb(${d.r},${d.g},${d.b})`;
                ctx.fillText(d.text, d.x, d.y);
                break;
            case 'box':
                ctx.fillStyle = `rgb(${d.r},${d.g},${d.b})`;
                ctx.fillRect(d.x1, d.y1, d.x2 - d.x1, d.y2 - d.y1);
                break;
            case 'image': {
                const img = new Image();
                img.src = d.src;
                img.onload = () => {
                    ctx.drawImage(img, d.x1, d.y1, d.x2 - d.x1, d.y2 - d.y1);
                };
                img.onerror = () => {
                    console.error('Failed to load image:', d.src);
                };
                break;
            }
            case 'ellipse':
                ctx.fillStyle = `rgb(${d.r},${d.g},${d.b})`;
                ctx.beginPath();
                ctx.ellipse(
                    (d.x1 + d.x2) / 2,
                    (d.y1 + d.y2) / 2,
                    Math.abs(d.x2 - d.x1) / 2,
                    Math.abs(d.y2 - d.y1) / 2,
                    0, 0, 2 * Math.PI
                );
                ctx.fill();
                break;
            default:
                console.warn('Unsupported object type:', obj.type);
        }
    }
}

/**
 * Download the selected card's data as a JSON file.
 * @param {string} cardName - The name of the card to download.
 */
export function downloadCardJSON(cardName) {
    const cardsList = importCardsList();
    const cardData = cardsList[cardName];
    
    if (!cardData) {
        alert('No card found');
        return;
    }

    const jsonStr = JSON.stringify(cardData, null, 2);
    const blob = new Blob([jsonStr], { type: 'application/json' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `${cardName.replace(/[^a-z0-9]/gi, '_')}.json`;
    document.body.appendChild(a);
    a.click();
    setTimeout(() => {
        document.body.removeChild(a);
        URL.revokeObjectURL(url);
    }, 100);
}

/**
 * Save the updated card list to local storage.
 * @param {Object} cardsList - The full card list to save.
 */
export function saveCardsList(cardsList) {
    localStorage.setItem('cards', JSON.stringify(cardsList));
}

/**
 * Set up the upload button to allow file uploads via dialog or drag-drop.
 */
export function uploadFeature() {
    const uploadBtn = document.querySelector('.icon-button.upload');
    
    uploadBtn.addEventListener('click', () => {
        let files;
        const overlay = document.createElement('div');
        overlay.id = "overlay";
        const dialogBox = document.createElement('div');
        dialogBox.id = "dialogBox";

        const dropZone = document.createElement('div');
        dropZone.id = "dropZone";
        dropZone.innerText = 'Drag and drop a file here';
        dropZone.ondrop = (e) => {
            e.preventDefault();
            files = e.dataTransfer.files;
            dropZone.innerText = dropZone.innerText + '\n' + 'You droped: \n' + files[0].name;
            confirmBtn.disabled = false;  
        };

        dropZone.ondragover = (e) => {
            e.preventDefault();
            dropZone.style.backgroundColor = '#e0f7fa';
        };

        dropZone.ondragleave = () => {
            dropZone.style.backgroundColor = '#f9f9f9';
        };

        const fileInput = document.createElement('input');
        fileInput.type = 'file';
        fileInput.style.marginTop = '10px';
        fileInput.onchange = (e) => {
            files = e.target.files;
            confirmBtn.disabled = false;  
        };
        
        const cancelBtn = document.createElement('button');
        cancelBtn.id = "cancelBtn";
        cancelBtn.innerText = "Cancel";

        const confirmBtn = document.createElement('button');
        confirmBtn.id = "confirmBtn";
        confirmBtn.innerText = "Confirm";
        confirmBtn.disabled = true;

        confirmBtn.addEventListener('click', () => {
            if (files) {
                handleFiles(files);
            }
        });

        cancelBtn.addEventListener('click', (e) => {
            document.body.removeChild(overlay);
        });

        dialogBox.appendChild(dropZone);
        dialogBox.appendChild(fileInput);
        dialogBox.appendChild(cancelBtn);
        dialogBox.appendChild(confirmBtn);

        overlay.appendChild(dialogBox);
        document.body.appendChild(overlay);

        overlay.addEventListener('click', (e) => {
            if (e.target === overlay) {
                document.body.removeChild(overlay);
            }
        });
    });
}

/**
 * Delete a specific card from local storage and trigger a UI update.
 * @param {string} cardName - The name of the card to delete.
 * @returns {Promise<boolean>} - True if deleted, false if card not found.
 */
export async function deleteCard(cardName) {
    const cardsList = await importCardsList();
    if (!cardsList[cardName]) {
        console.error('Cards not found:', cardName);
        return false;
    }

    if (getStarStatus(cardName)) {
        localStorage.removeItem('star');
    }

    delete cardsList[cardName];
    saveCardsList(cardsList); 
    window.dispatchEvent(new Event('cardsUpdated'));
    return true;
}

/**
 * Handle the logic to star or unstar a card. Only one card can be starred.
 * @param {string} cardName - The name of the card to (un)star.
 * @param {Object} cardData - The card data to store if starring.
 * @returns {Object} - Action result and success flag.
 */
export function handleStarCard(cardName, cardData) {
    const starredCard = JSON.parse(localStorage.getItem('star'));
    
    if (starredCard && starredCard.name === cardName) {
        localStorage.removeItem('star');
        // window.dispatchEvent(new Event('cardsUpdated'));
        return { action: 'unstar', success: true };
    } else if (starredCard) {
        alert(`You have starred card: ${starredCard.name}\nPlease unstar it first!`);
        return { action: 'rejected', success: false };
    } else {
        localStorage.setItem('star', JSON.stringify({
            name: cardName,
            data: cardData,
            timestamp: new Date().getTime()
        }));
        window.dispatchEvent(new Event('cardsUpdated'));
        return { action: 'star', success: true };
    }
}

/**
 * Check if a specific card is currently starred.
 * @param {string} cardName - The name of the card to check.
 * @returns {boolean} - True if the card is starred.
 */
export function getStarStatus(cardName) {
    const starredCard = JSON.parse(localStorage.getItem('star'));
    return starredCard && starredCard.name === cardName;
}


window.addEventListener('DOMContentLoaded', () => {
    const container = document.querySelector('.show');
    container.innerHTML = '';
    let currentPreviewCard = null; 
    let starBtn = null; 

    const previewModal = document.createElement('div');
    previewModal.classList.add('preview-modal');
    previewModal.style.display = 'none';
    document.body.appendChild(previewModal);

    const previewContent = document.createElement('div');
    previewContent.classList.add('preview-content');
    previewModal.appendChild(previewContent);

    const closePreview = document.createElement('button');
    closePreview.classList.add('close-preview');
    const closeIcon = document.createElement('img');
    closeIcon.src = './icons/close.svg';
    closeIcon.alt = 'Close';
    closeIcon.style.width = '45px';
    closeIcon.style.height = '45px';
    closePreview.appendChild(closeIcon);
    previewContent.appendChild(closePreview);

    const mainContent = document.createElement('div');
    mainContent.classList.add('preview-main-content');
    previewContent.appendChild(mainContent);

    const actionButtons = document.createElement('div');
    actionButtons.classList.add('action-buttons');
    previewModal.appendChild(actionButtons); 

    uploadFeature();

    // add delete preview (confirmation)
    function deletePreview(){
        const deleteOverlay = document.createElement('div');
        deleteOverlay.id = "overlay";
        const deleteConfirmation = document.createElement('deleteConfirmation');
        deleteConfirmation.id = "dialogBox";
        const message = document.createElement('p');
        
        const cancelBtn = document.createElement('button');
        const confirmBtn = document.createElement('button');
        message.innerHTML = "Are you sure to delete this card?";
        cancelBtn.innerText = "Cancel";
        confirmBtn.innerText = "Confirm";
        cancelBtn.addEventListener('click', ()=> {
            document.body.removeChild(deleteOverlay);
        })

        confirmBtn.addEventListener('click', ()=>{
            if (deleteCard(currentPreviewCard)) {
                const cardElement = document.querySelector(`.view-card-button[data-card-name="${currentPreviewCard}"]`);
                if (cardElement) {
                    cardElement.remove();
                }
                previewModal.style.display = 'none';
            }
            window.location.reload();
        });
        
        deleteConfirmation.appendChild(message);
        deleteConfirmation.appendChild(cancelBtn);
        deleteConfirmation.appendChild(confirmBtn);
        deleteOverlay.appendChild(deleteConfirmation);
        document.body.appendChild(deleteOverlay);
    }

    // preview buttons
    const actionIcons = ['edit', 'star', 'download', 'delete'];
    actionIcons.forEach(icon => {
        const btn = document.createElement('button');
        btn.classList.add('action-button');
        
        const img = document.createElement('img');
        if (icon === 'star') {
            const flag = getStarStatus(currentPreviewCard);
            img.src = flag ? './icons/star-filled.svg' : `./icons/${icon}.svg`;
            starBtn = img; 
        } else {
            img.src = `./icons/${icon}.svg`;
        }
        img.alt = icon;
        img.style.width = '24px';
        img.style.height = '24px';
        
        btn.appendChild(img);
        actionButtons.appendChild(btn);
    
        btn.addEventListener('click', () => {
            if (!currentPreviewCard) {
                console.error('No card selected');
                return;
            }
            
            const cardsList = importCardsList();
            const cardData = cardsList[currentPreviewCard];
    
            switch(icon) {
                case 'edit':
                    localStorage.setItem('current_card', currentPreviewCard);
                    window.location.href = './editor-page.html';
                    break;
                case 'star':{
                    const result = handleStarCard(currentPreviewCard, cardData);
                    if (result.success) {
                        img.src = result.action === 'star' ? './icons/star-filled.svg' : './icons/star.svg';
                        starBtn = img; 
                    }
                    break;
                }
                case 'download':
                    downloadCardJSON(currentPreviewCard);
                    break;
                case 'delete':
                    deletePreview();
                    break;
            }
        });
    });

    // define preview page
    const canvasContainer = document.createElement('div');
    canvasContainer.classList.add('canvas-container');
    mainContent.appendChild(canvasContainer);

    const frontCanvas = document.createElement('canvas');
    frontCanvas.classList.add('preview-canvas', 'front');
    frontCanvas.width = 800;
    frontCanvas.height = 445;
    canvasContainer.appendChild(frontCanvas);

    const backCanvas = document.createElement('canvas');
    backCanvas.classList.add('preview-canvas', 'back');
    backCanvas.width = 800;
    backCanvas.height = 445;
    backCanvas.style.display = 'none';
    canvasContainer.appendChild(backCanvas);

    const navContainer = document.createElement('div');
    navContainer.classList.add('nav-container');
    mainContent.appendChild(navContainer);

    const leftArrow = document.createElement('button');
    leftArrow.classList.add('nav-button', 'left');
    leftArrow.style.display = 'none';
    const leftArrowImg = document.createElement('img');
    leftArrowImg.src = './icons/left.png';
    leftArrowImg.alt = 'Previous';
    leftArrowImg.style.width = '45px';
    leftArrowImg.style.height = '45px';
    leftArrow.appendChild(leftArrowImg);
    navContainer.appendChild(leftArrow);

    const rightArrow = document.createElement('button');
    rightArrow.classList.add('nav-button', 'right');
    const rightArrowImg = document.createElement('img');
    rightArrowImg.src = './icons/right.png';
    rightArrowImg.alt = 'Next';
    rightArrowImg.style.width = '45px';
    rightArrowImg.style.height = '45px';
    rightArrow.appendChild(rightArrowImg);
    navContainer.appendChild(rightArrow);

    let currentView = 'front';
    const toggleView = () => {
        if (currentView === 'front') {
            frontCanvas.style.display = 'none';
            backCanvas.style.display = 'block';
            leftArrow.style.display = 'block';
            rightArrow.style.display = 'none';
            currentView = 'back';
        } else {
            frontCanvas.style.display = 'block';
            backCanvas.style.display = 'none';
            leftArrow.style.display = 'none';
            rightArrow.style.display = 'block';
            currentView = 'front';
        }
    };

    leftArrow.addEventListener('click', toggleView);
    rightArrow.addEventListener('click', toggleView);

    closePreview.addEventListener('click', () => {
        previewModal.style.display = 'none';
        frontCanvas.style.display = 'block';
        backCanvas.style.display = 'none';
        leftArrow.style.display = 'none';
        rightArrow.style.display = 'block';
        currentView = 'front';

        const searchTerm = searchInput.value.trim();
        const cardsList = importCardsList();
        const filteredNames = filterCardsByName(cardsList, searchTerm);

        if (searchTerm && filteredNames.length > 0) {
            renderFilteredCards(cardsList, container, filteredNames);
        } else {
            renderFilteredCards(cardsList, container, Object.keys(cardsList));
        }

        suggestionsBox.style.display = 'none';
    });

    // define search function
    const searchButton = document.querySelector('.search-button');
    const searchInput = document.querySelector('.search-bar-view');
    const suggestionsBox = document.getElementById('search-suggestions');

    function performSearch() {
        const searchTerm = searchInput.value.trim();
        const cardsList = importCardsList();
        const filteredNames = filterCardsByName(cardsList, searchTerm);
        renderFilteredCards(cardsList, container, filteredNames);
        suggestionsBox.style.display = 'none';
    }

    searchInput.addEventListener('input', (e) => {
        const searchTerm = e.target.value.trim();
        const cardsList = importCardsList();
        
        if (searchTerm.length > 0) {
            const suggestions = filterCardsByName(cardsList, searchTerm);
            suggestionsBox.innerHTML = '';
            
            if (suggestions.length > 0) {
                suggestions.forEach(name => {
                    const item = document.createElement('div');
                    item.classList.add('suggestion-item');
                    item.textContent = name;
                    item.addEventListener('click', () => {
                        searchInput.value = name;
                        performSearch();
                    });
                    suggestionsBox.appendChild(item);
                });
                suggestionsBox.style.display = 'block';
            } else {
                const noResults = document.createElement('div');
                noResults.classList.add('suggestion-item', 'no-results');
                noResults.textContent = 'No results found';
                suggestionsBox.appendChild(noResults);
                suggestionsBox.style.display = 'block';
            }
        } else {
            suggestionsBox.style.display = 'none';
            performSearch(); 
        }
    });

    searchButton.addEventListener('click', performSearch);
    searchInput.addEventListener('keypress', (e) => {
        if (e.key === 'Enter') {
            performSearch();
        }
    });

    /**
     * Filter card names by a search term (case-insensitive).
     * @param {Object} cardsList - The full card list.
     * @param {string} searchTerm - The term to filter by.
     * @returns {string[]} - Filtered list of card names.
     */
    function filterCardsByName(cardsList, searchTerm) {
        if (!searchTerm) return Object.keys(cardsList);
        return Object.keys(cardsList).filter(name => 
            name.toLowerCase().includes(searchTerm.toLowerCase()));
    }
    
    /**
     * Render the list of cards, placing starred card first if it exists.
     * @param {Object} cardsList - All cards.
     * @param {HTMLElement} container - The HTML element to render into.
     * @param {string[]} filteredNames - Filtered card name list to render.
     */
    function renderFilteredCards(cardsList, container, filteredNames) {
        container.innerHTML = '';
        const starredCard = JSON.parse(localStorage.getItem('star'));
        const starredCardName = starredCard?.name;

        let sortedNames = [...filteredNames];
        if (starredCardName && sortedNames.includes(starredCardName)) {
            sortedNames = [starredCardName, ...sortedNames.filter(name => name !== starredCardName)];
        }

        sortedNames.forEach(cardName => {
            const frontData = cardsList[cardName].front;
    
            const btnWrapper = document.createElement('div');
            btnWrapper.classList.add('view-card-button');
            btnWrapper.dataset.cardName = cardName;
    
            const button = document.createElement('button');
            button.classList.add('card-main-button');
            
            const flipContainer = document.createElement('div');
            flipContainer.classList.add('view-flip-container');
            
            const overlay = document.createElement('div');
            overlay.classList.add('overlay');
            flipContainer.appendChild(overlay);
            
            const buttonGroup = document.createElement('div');
            buttonGroup.classList.add('button-group');
            
            const icons = ['edit', 'star', 'download', 'delete'];
    
            for (let i = 0; i < 4; i++) {
                const btn = document.createElement('button');
                btn.classList.add('overlay-button');
    
                const img = document.createElement('img');
                img.src = `./icons/${icons[i]}.svg`;
                if (icons[i] === 'star') {
                    img.src = getStarStatus(cardName) ? './icons/star-filled.svg' : `./icons/${icons[i]}.svg`;
                }
                    
                img.alt = icons[i];
                img.style.width = '25px';
                img.style.height = '25px';
    
                btn.appendChild(img);
                buttonGroup.appendChild(btn);
    
                btn.addEventListener('click', (e) => {
                    e.stopPropagation();
                    currentPreviewCard = cardName; 
    
                    const cardsList = importCardsList();
                    const cardData = cardsList[currentPreviewCard];
    
                    switch (icons[i]) {
                        case 'edit':
                            localStorage.setItem('current_card', currentPreviewCard);
                            window.location.href = `editor-page.html?card=${encodeURIComponent(currentPreviewCard)}`;
                            break;
                        case 'star':{
                            const result = handleStarCard(currentPreviewCard, cardData);
                            if (result.success) {
                                img.src = result.action === 'star' ? './icons/star-filled.svg' : './icons/star.svg';
                                if (starBtn) {
                                    starBtn.src = result.action === 'star' ? './icons/star-filled.svg' : './icons/star.svg';
                                }
                            }
                            break;
                        }
                        case 'download':
                            downloadCardJSON(currentPreviewCard);
                            break;
                        case 'delete':
                            deletePreview();
                            break;
                    }
                });
            }
    
            overlay.appendChild(buttonGroup);
    
            const cardFrontCanvas = document.createElement('canvas');
            cardFrontCanvas.classList.add('front-canvas');
            flipContainer.appendChild(cardFrontCanvas);
            button.appendChild(flipContainer);
            btnWrapper.appendChild(button);
            container.appendChild(btnWrapper);
    
            renderScaledPreview(cardFrontCanvas, frontData, 300, 167);
    
            button.addEventListener('click', (e) => {
                if (!e.target.closest('.overlay-button')) {
                    currentPreviewCard = cardName;
                    const cardsList = importCardsList();
                    if (!cardsList[cardName]) {
                        console.error('Card not found:', cardName);
                        return;
                    }
                    const frontData = cardsList[cardName].front;
                    const backData = cardsList[cardName].back;
                    if (!frontData || !backData) {
                        console.error('Invalid card data for:', cardName, frontData, backData);
                        return;
                    }
                    const isStarred = getStarStatus(cardName);
                    if (starBtn) {
                        starBtn.src = isStarred ? './icons/star-filled.svg' : './icons/star.svg';
                    } else {
                        console.warn('starBtn is not defined');
                    }
                    renderScaledPreview(frontCanvas, frontData, 800, 445);
                    renderScaledPreview(backCanvas, backData, 800, 445);
                    previewModal.style.display = 'flex';
                }
            });
        });
    }

    window.addEventListener('cardsUpdated', () => {
        if (previewModal.style.display === 'flex') {
            console.log('Preview modal is open, skipping re-render');
            return;
        }
        const searchTerm = searchInput.value.trim();
        const cardsList = importCardsList();
        const filteredNames = filterCardsByName(cardsList, searchTerm);

        if (searchTerm && filteredNames.length > 0) {
            renderFilteredCards(cardsList, container, filteredNames);
        } else {
            renderFilteredCards(cardsList, container, Object.keys(cardsList));
        }
    });

    // init rendering cards
    const cardsList = importCardsList();
    renderFilteredCards(cardsList, container, Object.keys(cardsList));
});