// AstroBin Image Overlay functionality for Aladin Lite

function removeAstroBinImageLayer(imageLayer) {
    if (!imageLayer || !window.aladinInstance || !window.aladinInstance.aladin) {
        return;
    }

    try {
        window.aladinInstance.aladin.removeImageLayer(imageLayer);
        return;
    } catch (error) {
        if (imageLayer.layer) {
            window.aladinInstance.aladin.removeImageLayer(imageLayer.layer);
            return;
        }

        throw error;
    }
}

function isLegacyAladinBuild() {
    return !!window.aladinInstance?.aladin?.__amLegacyBuild;
}

function getAstroBinOverlayHost() {
    const aladinDiv = window.aladinInstance?.aladin?.aladinDiv;
    if (!aladinDiv) {
        return null;
    }

    if (!aladinDiv.style.position) {
        aladinDiv.style.position = 'relative';
    }

    return aladinDiv;
}

function ensureAstroBinDomRefreshHook() {
    if (window.__amAstroBinDomRefreshHookInstalled) {
        return;
    }

    window.__amAstroBinDomRefreshHookInstalled = true;

    const refresh = () => {
        if (!window.astroBinOverlays) {
            return;
        }

        for (const [, overlayInfo] of window.astroBinOverlays.entries()) {
            if (overlayInfo?.mode === 'legacy-dom') {
                updateLegacyAstroBinDomOverlay(overlayInfo);
            }
        }
    };

    window.__amRefreshAstroBinDomOverlays = refresh;

    const aladin = window.aladinInstance?.aladin;
    if (aladin?.on) {
        try {
            aladin.on('positionChanged', refresh);
            aladin.on('zoomChanged', refresh);
            aladin.on('fovChanged', refresh);
        } catch (error) {
            console.warn('[AstroBinDebug] Failed to attach legacy DOM overlay listeners', error);
        }
    }

    if (window.ResizeObserver && aladin?.aladinDiv) {
        const observer = new ResizeObserver(() => refresh());
        observer.observe(aladin.aladinDiv);
        window.__amAstroBinDomResizeObserver = observer;
    }

    window.addEventListener('resize', refresh, { passive: true });
    window.addEventListener('orientationchange', refresh, { passive: true });
}

function projectAstroBinOverlayDimensionsPx(overlayData) {
    const aladin = window.aladinInstance?.aladin;
    const container = aladin?.aladinDiv;
    if (!aladin || !container) {
        return null;
    }

    const widthDegrees = Number(overlayData.widthDegrees) || 0;
    const heightDegrees = Number(overlayData.heightDegrees) || 0;
    const centerRa = Number(overlayData.ra) || 0;
    const centerDec = Number(overlayData.dec) || 0;
    const fov = aladin.getFov?.() || [1, 1];
    const containerWidth = container.offsetWidth || 0;
    const containerHeight = container.offsetHeight || 0;
    const cosDec = Math.max(Math.abs(Math.cos(centerDec * Math.PI / 180)), 0.05);
    const halfWidthRaDegrees = (widthDegrees / 2) / cosDec;
    const halfHeightDegrees = heightDegrees / 2;

    const safeWorld2Pix = (ra, dec) => {
        try {
            const point = aladin.world2pix?.(ra, dec);
            return Array.isArray(point) && point.length >= 2
                && Number.isFinite(point[0]) && Number.isFinite(point[1])
                ? point
                : null;
        } catch {
            return null;
        }
    };

    const left = safeWorld2Pix(centerRa - halfWidthRaDegrees, centerDec);
    const right = safeWorld2Pix(centerRa + halfWidthRaDegrees, centerDec);
    const top = safeWorld2Pix(centerRa, centerDec + halfHeightDegrees);
    const bottom = safeWorld2Pix(centerRa, centerDec - halfHeightDegrees);

    const projectedWidthPx = left && right ? Math.abs(right[0] - left[0]) : 0;
    const projectedHeightPx = top && bottom ? Math.abs(bottom[1] - top[1]) : 0;
    const fallbackWidthPx = widthDegrees * (containerWidth / Math.max(fov[0] || 1, 0.0001));
    const fallbackHeightPx = heightDegrees * (containerHeight / Math.max((fov[1] || fov[0] || 1), 0.0001));

    return {
        widthPx: projectedWidthPx || fallbackWidthPx,
        heightPx: projectedHeightPx || fallbackHeightPx
    };
}

function updateLegacyAstroBinDomOverlay(overlayInfo) {
    if (!overlayInfo?.element || !overlayInfo?.data || !window.aladinInstance?.aladin) {
        return;
    }

    const aladin = window.aladinInstance.aladin;
    const centerPoint = aladin.world2pix?.(overlayInfo.data.ra, overlayInfo.data.dec);
    if (!Array.isArray(centerPoint) || centerPoint.length < 2 || !Number.isFinite(centerPoint[0]) || !Number.isFinite(centerPoint[1])) {
        overlayInfo.element.style.display = 'none';
        return;
    }

    const dimensions = projectAstroBinOverlayDimensionsPx(overlayInfo.data);
    if (!dimensions || !Number.isFinite(dimensions.widthPx) || !Number.isFinite(dimensions.heightPx) || dimensions.widthPx <= 1 || dimensions.heightPx <= 1) {
        overlayInfo.element.style.display = 'none';
        return;
    }

    overlayInfo.element.style.display = overlayInfo.data.isVisible === false ? 'none' : 'block';
    overlayInfo.element.style.left = `${centerPoint[0]}px`;
    overlayInfo.element.style.top = `${centerPoint[1]}px`;
    overlayInfo.element.style.width = `${dimensions.widthPx}px`;
    overlayInfo.element.style.height = `${dimensions.heightPx}px`;
    overlayInfo.element.style.opacity = `${overlayInfo.data.opacity ?? 0.78}`;
    overlayInfo.element.style.transform = `translate(-50%, -50%) rotate(${overlayInfo.data.rotation || 0}deg)`;
}

function createLegacyAstroBinDomOverlay(overlayData) {
    const host = getAstroBinOverlayHost();
    if (!host) {
        throw new Error('Aladin overlay host not available for legacy AstroBin overlay');
    }

    ensureAstroBinDomRefreshHook();

    const wrapper = document.createElement('div');
    wrapper.className = 'am-astrobin-overlay am-astrobin-overlay--legacy';
    wrapper.style.position = 'absolute';
    wrapper.style.pointerEvents = 'none';
    wrapper.style.transformOrigin = 'center center';
    wrapper.style.zIndex = '12';
    wrapper.style.overflow = 'hidden';
    wrapper.style.border = '1px solid rgba(255,255,255,0.22)';
    wrapper.style.boxShadow = '0 10px 30px rgba(0,0,0,0.22)';
    wrapper.style.background = 'transparent';

    const image = document.createElement('img');
    image.alt = overlayData.name || 'AstroBin overlay';
    image.src = overlayData.imageUrl;
    image.draggable = false;
    image.style.width = '100%';
    image.style.height = '100%';
    image.style.objectFit = 'fill';
    image.style.pointerEvents = 'none';
    image.style.userSelect = 'none';
    image.style.display = 'block';
    image.style.opacity = `${overlayData.opacity ?? 0.78}`;

    wrapper.appendChild(image);
    host.appendChild(wrapper);

    const overlayInfo = {
        mode: 'legacy-dom',
        overlay: null,
        element: wrapper,
        imageElement: image,
        data: { ...overlayData, isVisible: true }
    };

    updateLegacyAstroBinDomOverlay(overlayInfo);
    return overlayInfo;
}

/**
 * Add an AstroBin image as an overlay to the Aladin instance
 * @param {Object} overlayData - The overlay configuration
 * @param {string} overlayData.id - Unique identifier for the overlay
 * @param {string} overlayData.name - Display name for the overlay
 * @param {string} overlayData.imageUrl - URL to the AstroBin image
 * @param {number} overlayData.ra - Right Ascension in degrees
 * @param {number} overlayData.dec - Declination in degrees
 * @param {number} overlayData.widthDegrees - Image width in degrees
 * @param {number} overlayData.heightDegrees - Image height in degrees
 * @param {number} overlayData.rotation - Image rotation in degrees
 * @param {number} overlayData.opacity - Opacity (0.0 to 1.0)
 * @param {number} overlayData.width - Image width in pixels
 * @param {number} overlayData.height - Image height in pixels
 * @param {number} overlayData.pixelScale - Pixel scale in arcsec/pixel
 */
function addAstroBinImageOverlay(overlayData) {
    try {
        if (!window.aladinInstance) {
            console.error('Aladin instance not found');
            return;
        }

        const debugImageUrl = typeof overlayData.imageUrl === 'string' && overlayData.imageUrl.startsWith('data:')
            ? `${overlayData.imageUrl.substring(0, 64)}...`
            : overlayData.imageUrl;

        console.debug('[AstroBinDebug] addAstroBinImageOverlay start', {
            id: overlayData.id,
            name: overlayData.name,
            imageUrl: debugImageUrl,
            imageFormat: overlayData.imageFormat,
            ra: overlayData.ra,
            dec: overlayData.dec,
            widthDegrees: overlayData.widthDegrees,
            heightDegrees: overlayData.heightDegrees,
            width: overlayData.width,
            height: overlayData.height,
            widthFull: overlayData.width_full,
            heightFull: overlayData.height_full,
            pixelScale: overlayData.pixelScale,
            rotation: overlayData.rotation
        });

        if (!window.astroBinOverlays) {
            window.astroBinOverlays = new Map();
        }

        if (window.astroBinOverlays.has(overlayData.id)) {
            removeAstroBinImageOverlay(overlayData.id);
        }

        if (isLegacyAladinBuild()) {
            const overlayInfo = createLegacyAstroBinDomOverlay(overlayData);
            window.astroBinOverlays.set(overlayData.id, overlayInfo);
            return;
        }

        // Calculate the image bounds based on center coordinates and FOV
        const centerRa = overlayData.ra;
        const centerDec = overlayData.dec;
        const widthDegrees = overlayData.widthDegrees;
        const heightDegrees = overlayData.heightDegrees;
        
        // Calculate corner coordinates for the image
        const halfWidthRa = (widthDegrees / 2) / Math.cos(centerDec * Math.PI / 180); // Adjust for declination
        const halfHeightDec = heightDegrees / 2;
        
        // Define image corners (before rotation)
        const corners = [
            [centerRa - halfWidthRa, centerDec - halfHeightDec], // Bottom-left
            [centerRa + halfWidthRa, centerDec - halfHeightDec], // Bottom-right
            [centerRa + halfWidthRa, centerDec + halfHeightDec], // Top-right
            [centerRa - halfWidthRa, centerDec + halfHeightDec]  // Top-left
        ];

        // Apply rotation if specified
        if (overlayData.rotation && overlayData.rotation !== 0) {
            const rotationRad = overlayData.rotation * Math.PI / 180;
            const cosRot = Math.cos(rotationRad);
            const sinRot = Math.sin(rotationRad);
            
            for (let i = 0; i < corners.length; i++) {
                const deltaRa = corners[i][0] - centerRa;
                const deltaDec = corners[i][1] - centerDec;
                
                corners[i][0] = centerRa + (deltaRa * cosRot - deltaDec * sinRot);
                corners[i][1] = centerDec + (deltaRa * sinRot + deltaDec * cosRot);
            }
        }

        // Calculate WCS parameters for Aladin (similar to addImageLayer in aladin.js)
        // Adjust pixel scale for compression ratio from full-size to HD version
        const compressionRatioWidth = overlayData.width_full / overlayData.width;
        const compressionRatioHeight = overlayData.height_full / overlayData.height;
        const avgCompressionRatio = (compressionRatioWidth + compressionRatioHeight) / 2;
        
        const adjustedPixelScale = overlayData.pixelScale * avgCompressionRatio;
        const pixelScaleDeg = adjustedPixelScale / 3600; // Convert arcsec to degrees
        const rotationRad = (overlayData.rotation || 0) * Math.PI / 180;
        const imageFormat = overlayData.imageFormat || 'jpg';

        console.debug('[AstroBinDebug] addAstroBinImageOverlay derived', {
            id: overlayData.id,
            compressionRatioWidth,
            compressionRatioHeight,
            avgCompressionRatio,
            adjustedPixelScale,
            pixelScaleDeg,
            rotationRad,
            imageFormat
        });

        const debugProbeImage = new Image();
        debugProbeImage.onload = () => {
            console.debug('[AstroBinDebug] image probe load success', {
                id: overlayData.id,
                naturalWidth: debugProbeImage.naturalWidth,
                naturalHeight: debugProbeImage.naturalHeight,
                currentSrc: debugProbeImage.currentSrc
            });
        };
        debugProbeImage.onerror = (event) => {
            console.error('[AstroBinDebug] image probe load failed', {
                id: overlayData.id,
                imageUrl: debugImageUrl,
                imageFormat,
                event
            });
        };
        debugProbeImage.src = overlayData.imageUrl;
        
        if (!overlayData.disableAutoFocus) {
            window.aladinInstance.gotoRaDec(centerRa, centerDec);

            const maxDimension = Math.max(widthDegrees, heightDegrees);
            const viewFov = Math.max(maxDimension * 1.5, 0.1);
            window.aladinInstance.setFov(viewFov);
        }

        // Create image layer using Aladin's image functionality with WCS
        const imageLayer = window.A.image(overlayData.imageUrl, {
            name: overlayData.name,
            imgFormat: imageFormat,
            wcs: {
                NAXIS: 2,
                CTYPE1: 'RA---TAN',
                CTYPE2: 'DEC--TAN', 
                EQUINOX: 2000.0,
                LONPOLE: 180.0,
                LATPOLE: 0.0,
                CRVAL1: overlayData.ra,        // RA at reference pixel
                CRVAL2: overlayData.dec,       // Dec at reference pixel
                CRPIX1: overlayData.width / 2, // Reference pixel X
                CRPIX2: overlayData.height / 2, // Reference pixel Y
                CD1_1: -pixelScaleDeg * Math.cos(rotationRad),
                CD1_2: pixelScaleDeg * Math.sin(rotationRad),
                CD2_1: pixelScaleDeg * Math.sin(rotationRad),
                CD2_2: pixelScaleDeg * Math.cos(rotationRad),
                NAXIS1: overlayData.width,
                NAXIS2: overlayData.height,
            }
            /*,
            successCallback: (ra, dec, fov, image) => {
                window.aladinInstance.gotoRaDec(ra, dec);
                window.aladinInstance.setFov(fov * 5);

            }
            */
        });

        console.debug('[AstroBinDebug] window.A.image created', {
            id: overlayData.id,
            imageFormat,
            hasLayer: !!imageLayer
        });

        // Add the image layer to Aladin (use the raw aladin instance, not the wrapper)
        window.aladinInstance.aladin.addNewImageLayer(imageLayer);

        // Store reference for later management
        window.astroBinOverlays.set(overlayData.id, {
            mode: 'v3-image-layer',
            overlay: imageLayer,
            data: { ...overlayData, isVisible: true }
        });

    } catch (error) {
        console.error('[AstroBinDebug] Error adding AstroBin image overlay', {
            error,
            overlayData
        });
        throw error;
    }
}

/**
 * Toggle visibility of an AstroBin image overlay
 * @param {string} overlayId - The ID of the overlay to toggle
 * @returns {boolean} - New visibility state (true = visible, false = hidden)
 */
function toggleAstroBinImageOverlay(overlayId) {
    try {
        if (!window.astroBinOverlays || !window.astroBinOverlays.has(overlayId)) {
            console.warn(`AstroBin overlay with ID '${overlayId}' not found`);
            return false;
        }

        const overlayInfo = window.astroBinOverlays.get(overlayId);

        if (overlayInfo.mode === 'legacy-dom' && overlayInfo.element) {
            const isVisible = !overlayInfo.data.isVisible;
            overlayInfo.data.isVisible = isVisible;
            overlayInfo.element.style.display = isVisible ? 'block' : 'none';

            if (isVisible === true && overlayInfo.data.recenterOnShow !== false) {
                window.aladinInstance.gotoRaDec(overlayInfo.data.ra, overlayInfo.data.dec);
                window.__amRefreshAstroBinDomOverlays?.();
            }

            return isVisible;
        }

        // Toggle the image layer visibility using Aladin's toggle method
        if (overlayInfo.overlay && overlayInfo.overlay.toggle) {
            const isVisible = !overlayInfo.data.isVisible;
            overlayInfo.overlay.toggle();
            overlayInfo.data.isVisible = isVisible;

            if (isVisible === true && overlayInfo.data.recenterOnShow !== false) {
                window.aladinInstance.gotoRaDec(overlayInfo.data.ra, overlayInfo.data.dec);
            }

            return isVisible;
        } else {
            console.warn(`AstroBin overlay '${overlayId}' does not support toggle functionality`);
            return false;
        }
    } catch (error) {
        console.error('Error toggling AstroBin image overlay:', error);
        return false;
    }
}

/**
 * Remove an AstroBin image overlay (permanently)
 * @param {string} overlayId - The ID of the overlay to remove
 */
function removeAstroBinImageOverlay(overlayId) {
    try {
        if (!window.astroBinOverlays || !window.astroBinOverlays.has(overlayId)) {
            console.warn(`AstroBin overlay with ID '${overlayId}' not found`);
            return;
        }

        const overlayInfo = window.astroBinOverlays.get(overlayId);

        if (overlayInfo.mode === 'legacy-dom' && overlayInfo.element) {
            overlayInfo.element.remove();
        } else if (overlayInfo.overlay) {
            // Remove the image layer from Aladin using the stored layer reference
            removeAstroBinImageLayer(overlayInfo.overlay);
        }
        
        // Remove from our tracking map
        window.astroBinOverlays.delete(overlayId);

    } catch (error) {
        console.error('Error removing AstroBin image overlay:', error);
    }
}

/**
 * Update the opacity of an AstroBin image overlay
 * @param {string} overlayId - The ID of the overlay to update
 * @param {number} opacity - New opacity value (0.0 to 1.0)
 */
function updateAstroBinOverlayOpacity(overlayId, opacity) {
    try {
        if (!window.astroBinOverlays || !window.astroBinOverlays.has(overlayId)) {
            console.warn(`AstroBin overlay with ID '${overlayId}' not found`);
            return;
        }

        const overlayInfo = window.astroBinOverlays.get(overlayId);
        overlayInfo.data.opacity = opacity;

        if (overlayInfo.mode === 'legacy-dom' && overlayInfo.imageElement) {
            overlayInfo.imageElement.style.opacity = `${opacity}`;
            return;
        }

        // Note: Aladin image layers may not support setOpacity directly
        // This would need to be implemented if opacity control is required

    } catch (error) {
        console.error('Error updating AstroBin overlay opacity:', error);
    }
}

/**
 * Get all active AstroBin overlays
 * @returns {Array} Array of overlay information
 */
function getAstroBinOverlays() {
    if (!window.astroBinOverlays) {
        return [];
    }

    return Array.from(window.astroBinOverlays.entries()).map(([id, info]) => ({
        id: id,
        name: info.data.name,
        opacity: info.data.opacity,
        ra: info.data.ra,
        dec: info.data.dec,
        widthDegrees: info.data.widthDegrees,
        heightDegrees: info.data.heightDegrees
    }));
}

/**
 * Clear all AstroBin image overlays
 */
function clearAllAstroBinOverlays() {
    try {
        if (!window.astroBinOverlays) {
            return;
        }

        // Remove each layer individually using the proper method
        for (const [overlayId, overlayInfo] of window.astroBinOverlays.entries()) {
            if (overlayInfo.overlay) {
                removeAstroBinImageLayer(overlayInfo.overlay);
            }
        }
        
        // Clear the tracking map
        window.astroBinOverlays.clear();
    } catch (error) {
        console.error('Error clearing AstroBin overlays:', error);
    }
}

// Make functions globally available
window.addAstroBinImageOverlay = addAstroBinImageOverlay;
window.toggleAstroBinImageOverlay = toggleAstroBinImageOverlay;
window.removeAstroBinImageOverlay = removeAstroBinImageOverlay;
window.updateAstroBinOverlayOpacity = updateAstroBinOverlayOpacity;
window.getAstroBinOverlays = getAstroBinOverlays;
window.clearAllAstroBinOverlays = clearAllAstroBinOverlays;
