// js/imageSelectionDialog.js

const fileListFile = './json/image_list.txt'; // Path to filelist.txt relative to this script
const lastKnownPathKey = 'lastKnownFilePath';
const imageBaseDirName = '' // '../pics'; // The folder containing your images (e.g., img/pics/)
const customImagePathPrefix = ''; // The base URL path to your addon
const imageFullBaseDirPath = customImagePathPrefix + imageBaseDirName + '/'; // The complete base URL path to images
const allowedImageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.svg'];

// Create the dialog overlay element and append it to the body
const fileDialogOverlay = document.createElement('div');
fileDialogOverlay.id = 'fileDialogOverlay';
fileDialogOverlay.classList.add('overlay', 'hidden');
fileDialogOverlay.innerHTML = `
    <div class="file-dialog">
        <div class="file-dialog-header">Select Image</div>
        <div class="file-dialog-path">Current Path: <span id="currentPathDisplay">/</span></div>

        <div class="file-dialog-filter">
            <input type="text" id="filterInput" placeholder="Filter file names...">
        </div>

        <div id="fileDialogContent" class="file-dialog-content">
            <!-- Folder and file list will be dynamically inserted here -->
        </div>

        <div class="file-dialog-buttons">
            <div id="imagePreviewSection" class="image-preview-section">
                <img id="imagePreview" src="" alt="Image Preview" class="image-preview">
            </div>
            <div class="file-dialog-button-group">
                <button id="okBtn" disabled>OK</button>
                <button id="cancelBtn">Cancel</button>
            </div>
        </div>
    </div>
`;
document.body.appendChild(fileDialogOverlay);

// Get references to dialog elements once they are in the DOM
const fileDialogContent = fileDialogOverlay.querySelector('#fileDialogContent');
const currentPathDisplay = fileDialogOverlay.querySelector('#currentPathDisplay');
const filterInput = fileDialogOverlay.querySelector('#filterInput');
const okBtn = fileDialogOverlay.querySelector('#okBtn');
const cancelBtn = fileDialogOverlay.querySelector('#cancelBtn');

const imagePreviewSection = fileDialogOverlay.querySelector('#imagePreviewSection');
const imagePreview = fileDialogOverlay.querySelector('#imagePreview');

let fileTree = {}; // Stores the hierarchical file structure loaded from filelist.txt
let currentFolder = fileTree; // Represents the current folder object in the fileTree
let currentPathParts = []; // Array of path segments from the base image folder (e.g., ['icons', 'subfolder'])
let selectedItem = null; // Stores data about the currently selected file/folder in the dialog

let resolvePromise; // A function to resolve the Promise returned by openImageSelectionDialog

// Inject CSS styles directly into the document head to ensure they are available
const style = document.createElement('style');
style.textContent = `
    /* Overlay Styles */
    .overlay {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background-color: rgba(0, 0, 0, 0.5);
        display: flex;
        justify-content: center;
        align-items: center;
        z-index: 1000;
    }

    .file-dialog {
        background-color: #fff;
        border-radius: 8px;
        box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
        width: 400px; /* Dialog width */
        height: 600px; /* Fixed dialog height */
        max-height: 90%; /* Max height in case of small viewport */
        max-width: 94%; /* Max width in case of small viewport */
        display: flex;
        flex-direction: column;
        overflow: hidden; /* Ensure content doesn't overflow */
    }

    .file-dialog-header {
        padding: 15px 20px;
        border-bottom: 1px solid #eee;
        font-size: 1.2em;
        font-weight: bold;
        color: #333;
    }

    .file-dialog-path {
        padding: 10px 20px;
        background-color: #f8f8f8;
        border-bottom: 1px solid #eee;
        font-size: 0.9em;
        color: #555;
        word-break: break-all;
    }

    /* Styling for the filter input field */
    .file-dialog-filter {
        padding: 10px 20px;
        background-color: #f0f0f0;
        border-bottom: 1px solid #eee;
        display: flex;
        align-items: center;
        gap: 10px;
    }

    .file-dialog-filter input {
        flex-grow: 1;
        padding: 8px 10px;
        border: 1px solid #ccc;
        border-radius: 4px;
        box-sizing: border-box;
        font-size: 0.9em;
    }

    .file-dialog-content {
        flex-grow: 1;
        overflow-y: auto;
        padding: 0;
    }

    .file-dialog-item {
        display: flex;
        align-items: center;
        padding: 8px 20px;
        cursor: pointer;
        border-bottom: 1px solid #e0e0e0;
        user-select: none;
        -webkit-user-select: none;
        -moz-user-select: none;
        -ms-user-select: none;
        outline: none;
    }
    .file-dialog-content .file-dialog-item:last-child {
        border-bottom: none;
    }

    .file-dialog-item:hover {
        background-color: #e9f5ff;
    }

    .file-dialog-item.selected {
        background-color: #d1e7ff;
    }

    .file-dialog-item.folder {
        color: #0056b3;
        font-weight: bold;
    }

    .file-dialog-item.file {
        color: #333;
    }

    .file-dialog-item.parent-dir {
        color: #007bff;
        font-style: italic;
    }

    .file-dialog-item i {
        margin-right: 10px;
        width: 20px;
        text-align: center;
    }

    /* Image Preview Section in Footer */
    .file-dialog-buttons {
        padding: 15px 20px;
        border-top: 1px solid #eee;
        display: flex;
        justify-content: space-between;
        align-items: center;
        gap: 10px;
    }

    /* Container for the buttons */
    .file-dialog-button-group {
        display: flex;
        gap: 10px;
    }

    .file-dialog-buttons button {
        padding: 8px 15px;
        border-radius: 5px;
        cursor: pointer;
        font-size: 0.9em;
    }

    .file-dialog-buttons #okBtn {
        background-color: #28a745;
        color: white;
        border: none;
    }

    .file-dialog-buttons #cancelBtn {
        background-color: #6c757d;
        color: white;
        border: none;
        height: 46px;
    }

    /* Image Preview styling for the dialog's specific preview image */
    #imagePreviewSection #imagePreview {
        width: 40px;
        height: 40px;
        border: 1px solid #ddd;
        background-color: #fff;
        object-fit: contain;
        transition: opacity 0.2s ease-in-out;
        opacity: 0; /* Default to hidden, JS will make it visible */
    }

    /* Common styles for icons */
    .icon-folder::before { content: "📁"; }
    .icon-file::before { content: "📄"; }
    .icon-up::before { content: "⬆️"; }
    .icon-file-image::before { content: "🖼️"; }

    /* Hidden by default (only for overlay) */
    .hidden {
        display: none !important;
    }
`;
document.head.appendChild(style); // Append the style element to the document head


/**
 * Builds a hierarchical JSON structure from a list of paths.
 * ASSUMPTION: Paths in filelist.txt are relative to the 'pics' folder.
 * File names are keys with the value 0. Folder names are keys with objects as their value.
 * @param {Array<string>} paths - An array of file paths.
 * @returns {object} The constructed hierarchical file tree.
 */
function buildJsonTree(paths) {
    let root = {};
    paths.forEach(originalPath => {
        const normalizedPath = originalPath.replace(/\\/g, '/');
        const arW = normalizedPath.split("/").filter(p => p !== ''); // Split path and filter out empty segments

        let jTmp = root; // Temporary pointer to navigate the tree
        for (let w = 0; w < arW.length; w++) {
            const part = arW[w];
            if (w === (arW.length - 1)) { // Last segment is a file
                if (typeof jTmp[part] !== 'object' || jTmp[part] === null) {
                    jTmp[part] = 0; // Mark as file
                }
            } else { // This segment is a folder
                if (typeof jTmp[part] !== 'object' || jTmp[part] === null || jTmp[part] === 0) {
                    jTmp[part] = {}; // Initialize as an empty object if not already a folder
                }
            }
            jTmp = jTmp[part]; // Move deeper into the tree
        }
    });
    return root;
}

/**
 * Loads the file list from filelist.txt, builds the file tree, and attempts to restore the last known path.
 */
async function loadFileList() {
    try {
        const response = await fetch(fileListFile);
        if (!response.ok) {
            if (response.status === 404) {
                throw new Error(`No file with image name found.\nCreate it with img-list.bat from AddOn installation directory`);
            } else
                throw new Error(`HTTP Error! Status: ${response.status} - ${response.statusText}`);
        }
        const text = await response.text();
        const allPaths = text.split('\n').map(line => line.trim()).filter(line => line.length > 0);

        fileTree = buildJsonTree(allPaths);

        let targetPathParts = [];
        const storedPath = localStorage.getItem(lastKnownPathKey);
        if (storedPath) {
            targetPathParts = storedPath.split('/');
        }

        let tempFolder = fileTree;
        currentPathParts = []; // Reset current path parts

        // Attempt to restore the previous path
        for (const part of targetPathParts) {
            if (tempFolder && typeof tempFolder === 'object' && tempFolder[part] !== undefined) {
                // If the part is a file but we're trying to navigate into it as a folder, reset path
                if (tempFolder[part] === 0 && part !== targetPathParts[targetPathParts.length - 1]) {
                    console.warn(`Path segment '${part}' is a file, but was treated as a folder in stored path '${targetPathParts.join('/')}'.`);
                    currentPathParts = [];
                    tempFolder = fileTree;
                    localStorage.removeItem(lastKnownPathKey);
                    break;
                }
                tempFolder = tempFolder[part];
                currentPathParts.push(part);
            } else {
                // Path part not found, fall back to root
                console.warn(`Path part '${part}' not found in file tree for path '${targetPathParts.join('/')}'. Falling back to root of '${imageBaseDirName}/' directory.`);
                currentPathParts = [];
                tempFolder = fileTree;
                localStorage.removeItem(lastKnownPathKey);
                break;
            }
        }
        currentFolder = tempFolder; // Set the current folder after path restoration attempt

        // Robust check: Ensure currentFolder is a valid directory object (not null, undefined, or a file marker)
        if (currentFolder === 0 || currentFolder === null || currentFolder === undefined || typeof currentFolder !== 'object') {
            console.error(`After path restoration, currentFolder is not a valid directory object (path: ${currentPathParts.join('/')}). Resetting to default root of '${imageBaseDirName}/' path.`);
            currentPathParts = [];
            currentFolder = fileTree;
            localStorage.removeItem(lastKnownPathKey);
            // If the entire tree (i.e., the 'pics' folder) is empty
            if (Object.keys(fileTree).length === 0) {
                fileDialogContent.innerHTML = `<p style="color: red; padding: 20px;">Error: '${imageBaseDirName}' directory is empty or 'filelist.txt' is empty/malformed (no content relative to '${imageBaseDirName}/').</p>`;
                return;
            }
        }
        renderFileList(); // Render the file list for the determined current folder
    } catch (error) {
        console.error("Error loading file list or building tree:", error);
        fileDialogContent.innerHTML = `<p style="color: red; padding: 20px;">Error loading: ${error.message}</p>`;
    }
}

/**
 * Renders the file list in the dialog content area based on the current folder and filter text.
 * @param {string} [filterText=''] - Optional text to filter file names.
 */
function renderFileList(filterText = '') {
    fileDialogContent.innerHTML = ''; // Clear current content
    okBtn.disabled = true; // Disable OK button by default
    selectedItem = null; // Clear selected item
    imagePreview.src = ''; // Clear image preview
    imagePreview.style.opacity = '0'; // Hide image preview

    // Display the current path, starting with /<imageBaseDirName>/
    const currentPathString = currentPathParts.length > 0 ? currentPathParts.join('/') : '';
    // currentPathDisplay.textContent = `/${currentPathString}`; 
    currentPathDisplay.textContent = `/${currentPathString}`.replace(/\/\/+/g, '/').replace(/\/..\//g, ''); // Remove any double slashes

    const itemsToDisplay = [];

    if (currentFolder && typeof currentFolder === 'object') {
        for (const key in currentFolder) {
            if (Object.prototype.hasOwnProperty.call(currentFolder, key)) {
                const value = currentFolder[key];
                const type = (value === 0) ? 'file' : 'folder';

                if (filterText === '' || key.toLowerCase().includes(filterText.toLowerCase())) {
                    // fullPath is relative to the root of the 'pics' tree (i.e., relative to 'pics/')
                    const fullPath = (currentPathParts.length > 0 ? currentPathParts.join('/') + '/' : '') + key;
                    itemsToDisplay.push({ name: key, type: type, fullPath: fullPath });
                }
            }
        }
    }

    // Sort items: folders first, then files, both alphabetically
    const sortedItems = itemsToDisplay.sort((a, b) => {
        if (a.type === 'folder' && b.type !== 'folder') return -1;
        if (a.type !== 'folder' && b.type === 'folder') return 1;
        return a.name.localeCompare(b.name);
    });

    // Add ".." for navigating up, if not at the root of the 'pics' tree
    if (currentPathParts.length > 0) {
        const parentDirItemDiv = document.createElement('div');
        parentDirItemDiv.classList.add('file-dialog-item', 'parent-dir');
        parentDirItemDiv.innerHTML = `<i class="icon-up"></i><span>..</span>`;
        parentDirItemDiv.setAttribute('tabindex', '-1'); // Make div focusable
        parentDirItemDiv.addEventListener('click', (e) => {
            e.preventDefault();
            selectItem(parentDirItemDiv, { name: '..', type: 'parent-dir' })
        });
        parentDirItemDiv.addEventListener('dblclick', navigateUp);
        fileDialogContent.appendChild(parentDirItemDiv);
    }

    // Display messages if folder is empty or filter yields no results
    if (sortedItems.length === 0 && currentPathParts.length === 0 && !filterText) {
        fileDialogContent.innerHTML = `<p style="padding: 20px;">The '${imageBaseDirName}' directory is empty or contains no valid entries.</p>`;
    } else if (sortedItems.length === 0 && filterText) {
        fileDialogContent.innerHTML = `<p style="padding: 20px;">No entries found matching filter "${filterText}".</p thoại;`;
    } else if (sortedItems.length === 0 && currentPathParts.length > 0) {
        fileDialogContent.innerHTML = `<p style="padding: 20px;">This folder is empty.</p>`;
    }

    // Render each item (folder or file)
    sortedItems.forEach(item => {
        const itemDiv = document.createElement('div');
        itemDiv.classList.add('file-dialog-item', item.type);

        let iconClass = `icon-${item.type}`;
        if (item.type === 'file' && isImageFile(item.name)) {
            iconClass = 'icon-file-image';
        }
        itemDiv.innerHTML = `<i class="${iconClass}"></i><span>${item.name}</span>`;
        itemDiv.setAttribute('tabindex', '-1'); // Make div focusable

        itemDiv.addEventListener('click', (e) => {
            e.preventDefault();
            selectItem(itemDiv, item)
        });
        itemDiv.addEventListener('dblclick', (e) => {
            e.preventDefault();
            if (item.type === 'folder') {
                navigateDown(item.name);
            } else {
                selectItem(itemDiv, item);
                if (okBtn.disabled === false) { // If a file is selected and OK is enabled
                    okBtn.click(); // Trigger OK button click on double click
                }
            }
        });
        fileDialogContent.appendChild(itemDiv);
    });
}

/**
 * Checks if a given filename has an allowed image extension.
 * @param {string} filename - The name of the file to check.
 * @returns {boolean} True if it's an image file, false otherwise.
 */
function isImageFile(filename) {
    const ext = '.' + filename.split('.').pop().toLowerCase();
    return allowedImageExtensions.includes(ext);
}

/**
 * Handles selection of an item in the file list.
 * @param {HTMLElement} element - The DOM element of the selected item.
 * @param {object} itemData - Data object for the selected item (name, type, fullPath).
 */
function selectItem(element, itemData) {
    // Remove 'selected' class from all other items
    document.querySelectorAll('.file-dialog-item.selected').forEach(el => {
        el.classList.remove('selected');
    });

    // Clear and hide image preview
    imagePreview.src = '';
    imagePreview.style.opacity = '0';

    // If the same item is clicked again, deselect it
    if (selectedItem && selectedItem.name === itemData.name && selectedItem.type === itemData.type) {
        selectedItem = null;
        okBtn.disabled = true;
    } else {
        element.classList.add('selected');
        selectedItem = itemData;

        // Enable OK button only if a file is selected
        okBtn.disabled = (selectedItem.type !== 'file');

        // Show image preview if an image file is selected
        if (selectedItem.type === 'file' && isImageFile(selectedItem.name)) {
            imagePreview.src = imageFullBaseDirPath + selectedItem.fullPath;
            imagePreview.style.opacity = '1';
        }
    }
}

/**
 * Navigates up one level in the directory tree.
 */
function navigateUp() {
    // Only navigate up if not at the root of the 'pics' tree
    if (currentPathParts.length > 0) {
        currentPathParts.pop(); // Remove last segment
        currentFolder = fileTree; // Start from the root of the 'pics' tree
        currentPathParts.forEach(part => {
            currentFolder = currentFolder[part]; // Re-traverse to the new current folder
        });
        filterInput.value = ''; // Clear filter
        renderFileList(); // Re-render the list
    } else {
        console.log("Already at the root of the image directory.");
    }
}

/**
 * Navigates down into a specified folder.
 * @param {string} folderName - The name of the folder to navigate into.
 */
function navigateDown(folderName) {
    // Check if the folder exists and is actually a folder
    if (currentFolder && typeof currentFolder === 'object' && currentFolder[folderName] !== undefined && currentFolder[folderName] !== 0) {
        currentPathParts.push(folderName); // Add folder to path
        currentFolder = currentFolder[folderName]; // Update current folder
        filterInput.value = ''; // Clear filter
        renderFileList(); // Re-render the list
    }
}

// Event Listeners for dialog buttons
cancelBtn.addEventListener('click', () => {
    fileDialogOverlay.classList.add('hidden');
    // Save the current path (relative to 'pics' folder)
    localStorage.setItem(lastKnownPathKey, currentPathParts.join('/'));
    resolvePromise(null); // Resolve the Promise with null on cancel
});

okBtn.addEventListener('click', () => {
    if (selectedItem && selectedItem.type === 'file') {
        const fullImagePath = imageFullBaseDirPath + selectedItem.fullPath;
        fileDialogOverlay.classList.add('hidden');
        localStorage.setItem(lastKnownPathKey, currentPathParts.join('/'));
        resolvePromise(fullImagePath); // Resolve with the full image path
    }
    // No else block needed; if OK is clicked but no file is selected, it's disabled.
});

// Event listener for the filter input field
filterInput.addEventListener('input', (event) => {
    renderFileList(event.target.value);
});

/**
 * Exports a function to open the image selection dialog.
 * This function returns a Promise that resolves with the selected image path (string)
 * or null if the dialog is canceled.
 * @returns {Promise<string|null>} A Promise that resolves with the selected image path (string)
 * or null (if canceled).
 */
export function openImageSelectionDialog() {
    return new Promise((resolve) => {
        resolvePromise = resolve; // Store the resolve function for the dialog buttons
        fileDialogOverlay.classList.remove('hidden'); // Show the dialog
        filterInput.value = ''; // Clear any previous filter
        loadFileList(); // Load and render the file list for the current folder
    });
}