import { AcGeVector2d } from '@mlightcad/data-model';
import * as THREE from 'three';
import { AcApDocManager } from '../app';
/**
 * Utility class for converting CAD drawings to PNG format.
 *
 * This class provides functionality to export the current CAD drawing
 * to PNG format and download it as a file. It renders the current view
 * using WebGLRenderTarget for optimal performance without requiring
 * preserveDrawingBuffer to be enabled on the renderer.
 *
 * The conversion process:
 * 1. Gets the current view and its associated renderer, scene, and camera
 * 2. Creates an offscreen render target for pixel capture
 * 3. Renders the scene to the render target
 * 4. Reads the pixel data and flips it vertically (WebGL renders upside down)
 * 5. Creates a canvas, draws the pixel data, and exports as PNG
 * 6. Triggers a download of the PNG file
 *
 * @example
 * ```typescript
 * const converter = new AcApPngConvertor();
 *
 * // Convert and download current drawing as PNG
 * converter.convert();
 * ```
 */
var AcApPngConvertor = /** @class */ (function () {
    function AcApPngConvertor() {
    }
    /**
     * Converts the current CAD drawing to PNG format and initiates download.
     *
     * This method:
     * - Retrieves the current view, renderer, scene, and camera
     * - Creates a WebGLRenderTarget for offscreen rendering
     * - Renders the scene to the render target
     * - Reads pixel data and flips it vertically to correct WebGL's upside-down rendering
     * - Creates a canvas with the pixel data
     * - Exports as PNG and downloads with timestamp-based filename
     *
     * @param bounds - Optional world coordinate bounding box to export.
     *                  If provided, the camera will zoom to fit this region.
     *                  If not provided, exports the current view.
     * @param long_side - Optional maximum dimension (width or height) in pixels for the output PNG.
     *                    The other dimension is calculated based on the aspect ratio of bounds.
     *                    If not provided, uses the current view dimensions.
     * @example
     * ```typescript
     * const converter = new AcApPngConvertor();
     * converter.convert(); // Downloads the drawing as PNG
     * ```
     *
     * @example
     * ```typescript
     * // Export a specific region
     * const bounds = new AcGeBox2d(new AcGePoint2d(0, 0), new AcGePoint2d(100, 100));
     * const converter = new AcApPngConvertor();
     * converter.convert(bounds); // Downloads the specified region as PNG
     * ```
     */
    AcApPngConvertor.prototype.convert = function (bounds, long_side) {
        var view = AcApDocManager.instance.curView;
        var renderer = view.renderer.internalRenderer;
        var scene = view.internalScene;
        var camera = view.internalCamera;
        if (!scene || !camera) {
            console.error('[PNGOUT] Scene or camera not available');
            return;
        }
        var outputWidth = view.width;
        var outputHeight = view.height;
        if (long_side && bounds) {
            var size = new AcGeVector2d();
            bounds.getSize(size);
            var boundsWidth = size.x;
            var boundsHeight = size.y;
            var boundsAspect = boundsWidth / boundsHeight;
            if (boundsAspect > 1) {
                outputWidth = long_side;
                outputHeight = Math.round(long_side / boundsAspect);
            }
            else {
                outputHeight = long_side;
                outputWidth = Math.round(long_side * boundsAspect);
            }
        }
        // Save original camera state for restoration later
        var originalZoom = camera.zoom;
        var originalPosition = camera.position.clone();
        // If bounds provided, calculate zoom and position to fit the specified region
        if (bounds) {
            var size = new AcGeVector2d();
            bounds.getSize(size);
            var center = new AcGeVector2d();
            bounds.getCenter(center);
            var boundsWidth = size.x;
            var boundsHeight = size.y;
            var widthRatio = view.width / boundsWidth;
            var heightRatio = view.height / boundsHeight;
            var scale = Math.min(widthRatio, heightRatio);
            // Set camera position to center of bounds and adjust zoom
            camera.position.set(center.x, center.y, camera.position.z);
            camera.zoom = scale;
            camera.updateProjectionMatrix();
        }
        // Create a render target for offscreen rendering
        var renderTarget = new THREE.WebGLRenderTarget(outputWidth, outputHeight, {
            minFilter: THREE.LinearFilter,
            magFilter: THREE.LinearFilter,
            format: THREE.RGBAFormat,
            type: THREE.UnsignedByteType
        });
        // Store the original render target
        var originalRenderTarget = renderer.getRenderTarget();
        // Render to the offscreen target
        renderer.setRenderTarget(renderTarget);
        renderer.render(scene, camera);
        // Read pixels from the render target
        var pixels = new Uint8Array(outputWidth * outputHeight * 4);
        renderer.readRenderTargetPixels(renderTarget, 0, 0, outputWidth, outputHeight, pixels);
        // Restore the original render target
        renderer.setRenderTarget(originalRenderTarget);
        // Clean up the render target
        renderTarget.dispose();
        // Restore original camera state
        camera.zoom = originalZoom;
        camera.position.copy(originalPosition);
        camera.updateProjectionMatrix();
        // Flip the image vertically (WebGL renders upside down)
        var flippedPixels = this.flipPixelsVertically(pixels, outputWidth, outputHeight);
        // Create canvas and draw the pixels
        var canvas = this.createCanvasFromPixels(flippedPixels, outputWidth, outputHeight);
        // Export to PNG and download
        this.createFileAndDownloadIt(canvas);
    };
    /**
     * Flips pixel data vertically to correct WebGL's upside-down rendering.
     *
     * WebGL renders images upside down (origin at bottom-left), so the pixel
     * data needs to be flipped to display correctly in standard image viewers.
     *
     * @param pixels - The raw pixel data from WebGL render target
     * @param width - Width of the image in pixels
     * @param height - Height of the image in pixels
     * @returns The vertically flipped pixel data
     * @private
     */
    AcApPngConvertor.prototype.flipPixelsVertically = function (pixels, width, height) {
        var flippedPixels = new Uint8Array(width * height * 4);
        for (var y = 0; y < height; y++) {
            var srcRow = (height - 1 - y) * width * 4;
            var dstRow = y * width * 4;
            for (var x = 0; x < width * 4; x++) {
                flippedPixels[dstRow + x] = pixels[srcRow + x];
            }
        }
        return flippedPixels;
    };
    /**
     * Creates a canvas element from pixel data.
     *
     * @param pixels - The vertically flipped pixel data
     * @param width - Width of the image in pixels
     * @param height - Height of the image in pixels
     * @returns A canvas element containing the image
     * @private
     */
    AcApPngConvertor.prototype.createCanvasFromPixels = function (pixels, width, height) {
        var canvas = document.createElement('canvas');
        canvas.width = width;
        canvas.height = height;
        var ctx = canvas.getContext('2d');
        var imageData = ctx.createImageData(width, height);
        imageData.data.set(pixels);
        ctx.putImageData(imageData, 0, 0);
        return canvas;
    };
    /**
     * Creates a downloadable PNG file and triggers the download.
     *
     * This method:
     * - Exports the canvas to a PNG data URL
     * - Generates a timestamped filename
     * - Creates and triggers a download link
     *
     * @param canvas - The canvas element containing the image
     * @private
     */
    AcApPngConvertor.prototype.createFileAndDownloadIt = function (canvas) {
        // Export canvas to PNG data URL
        var dataURL = canvas.toDataURL('image/png');
        // Create a download link and trigger the download
        var downloadLink = document.createElement('a');
        downloadLink.href = dataURL;
        downloadLink.download = "cad-export-".concat(Date.now(), ".png");
        // Trigger the download
        document.body.appendChild(downloadLink);
        downloadLink.click();
        document.body.removeChild(downloadLink);
    };
    return AcApPngConvertor;
}());
export { AcApPngConvertor };
//# sourceMappingURL=AcApPngConvertor.js.map