package dev.bytevibe.hyperpoint;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.imageio.ImageIO;

import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.RectangleReadOnly;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfWriter;

import javafx.scene.image.PixelReader;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.Pane;

/**
 * 导出工具类，用于导出页面为图片和导出幻灯片为PDF
 */
public class ExportUtil {

    /**
     * 导出页面为图片（PNG或JPG）
     *
     * @param pane 要导出的页面Pane
     * @param file 输出文件
     * @param format 图片格式 "png" 或 "jpg"
     * @throws IOException 如果导出失败
     */
    public static void exportPageAsImage(Pane pane, File file, String format) throws IOException {
        // 获取Pane的宽度和高度
        double width = pane.getWidth();
        double height = pane.getHeight();

        // 如果宽度或高度无效，尝试使用布局宽度/高度
        if (width <= 0 || height <= 0) {
            width = pane.getLayoutBounds().getWidth();
            height = pane.getLayoutBounds().getHeight();
        }

        // 如果仍然无效，使用固定的默认大小
        if (width <= 0) {
            width = 1024;
        }
        if (height <= 0) {
            height = 768;
        }

        // 创建WritableImage用于捕获页面内容
        WritableImage writableImage = new WritableImage((int) width, (int) height);
        pane.snapshot(null, writableImage);

        // 转换为BufferedImage
        BufferedImage bufferedImage = convertFXImageToBufferedImage(writableImage);

        // 写入文件
        String formatName = format.equalsIgnoreCase("jpg") ? "jpg" : "png";
        if (!ImageIO.write(bufferedImage, formatName, file)) {
            throw new IOException("无法写入" + formatName + "文件");
        }
    }

    /**
     * 将JavaFX WritableImage转换为BufferedImage
     */
    private static BufferedImage convertFXImageToBufferedImage(WritableImage fxImage) {
        int width = (int) fxImage.getWidth();
        int height = (int) fxImage.getHeight();
        BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

        PixelReader pixelReader = fxImage.getPixelReader();
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                int argb = pixelReader.getArgb(x, y);
                bufferedImage.setRGB(x, y, argb);
            }
        }

        return bufferedImage;
    }

    /**
     * 导出整个幻灯片为PDF
     *
     * @param slide 要导出的幻灯片
     * @param file 输出PDF文件
     * @throws Exception 如果导出失败
     */
    public static void exportSlideToPDF(Slide slide, File file) throws Exception {
        // 检查文件是否已存在且被占用
        if (file.exists()) {
            try (FileOutputStream fos = new FileOutputStream(file, false)) {
            } catch (IOException e) {
                throw new IOException("文件已被占用，请关闭该文件后重试：\n" + file.getAbsolutePath(), e);
            }
        }

        if (slide == null || slide.getPages().isEmpty()) {
            throw new IOException("幻灯片没有页面");
        }

        try (FileOutputStream fos = new FileOutputStream(file)) {
            // 创建PDF文档，使用与编辑界面相同的宽高比
            Document document = new Document(new RectangleReadOnly(
                (float)DrawingCanvas.PAGE_WIDTH, 
                (float)DrawingCanvas.PAGE_HEIGHT
            ));
            PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
            document.open();
            
            PdfContentByte canvas = writer.getDirectContent();

            // 为每一页添加内容
            for (SlidePage page : slide.getPages()) {
                // 添加页面标题
                Paragraph title = new Paragraph(page.getTitle(), new Font(
                    Font.FontFamily.HELVETICA, 16, Font.BOLD));
                title.setSpacingAfter(10);
                document.add(title);

                // 添加页面内容对象
                addObjectsToDocumentWithPosition(document, canvas, page.getPageContent());
                
                document.newPage();
            }

            document.close();
            writer.close();
        }
    }

    /**
     * 按位置添加对象到PDF文档
     */
    private static void addObjectsToDocumentWithPosition(Document document, PdfContentByte canvas, PageContent pageContent) throws DocumentException {
        float margin = 50;
        float pdfWidth = (float)(document.getPageSize().getWidth() - 2 * margin);
        float pdfHeight = (float)(document.getPageSize().getHeight() - 2 * margin);
        
        float scaleX = pdfWidth / (float)DrawingCanvas.PAGE_WIDTH;
        float scaleY = pdfHeight / (float)DrawingCanvas.PAGE_HEIGHT;
        float scale = Math.min(scaleX, scaleY);

        for (DrawableObject obj : pageContent.getDrawableObjects()) {
            float x = margin + (float)obj.getX() * scale;
            float y = margin + (float)(DrawingCanvas.PAGE_HEIGHT - obj.getY() - obj.getHeight()) * scale;
            float width = (float)obj.getWidth() * scale;
            float height = (float)obj.getHeight() * scale;

            if (obj instanceof TextObject) {
                addTextObjectWithPosition(canvas, (TextObject)obj, x, y, width, height);
            } else if (obj instanceof ShapeObject) {
                addShapeObjectWithPosition(canvas, (ShapeObject)obj, x, y, width, height);
            } else if (obj instanceof ImageObject) {
                addImageObjectWithPosition(document, canvas, (ImageObject)obj, x, y, width, height);
            }
        }
    }

    /**
     * 按位置添加文本对象
     */
    private static void addTextObjectWithPosition(PdfContentByte canvas, TextObject textObj, float x, float y, float width, float height) {
        try {
    
            // 处理字体
            BaseFont baseFont;
            String fontFamily = textObj.getFontFamily();
            if (fontFamily.contains("Times")) {
                baseFont = BaseFont.createFont(BaseFont.TIMES_ROMAN, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED);
            } else if (fontFamily.contains("Courier")) {
                baseFont = BaseFont.createFont(BaseFont.COURIER, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED);
            } else if (fontFamily.contains("Georgia")) {
                baseFont = BaseFont.createFont(BaseFont.TIMES_ROMAN, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED);
            } else if (fontFamily.contains("Verdana")) {
                baseFont = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED);
            } else {
                baseFont = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED);
            }
            
            // 处理字体样式（粗体/斜体）
            int style = Font.NORMAL;
            String fontStyle = textObj.getFontStyle();
            if (fontStyle.contains("BOLD")) style |= Font.BOLD;
            if (fontStyle.contains("ITALIC")) style |= Font.ITALIC;
            
            // 处理文本颜色
            BaseColor textColor = BaseColor.BLACK;
            if (textObj.getTextColor() != null && !textObj.getTextColor().isEmpty()) {
                Color fxColor = Color.decode("#" + textObj.getTextColor());
                textColor = new BaseColor(fxColor.getRed(), fxColor.getGreen(), fxColor.getBlue());
            }
            
            // 处理旋转
            double rotation = textObj.getRotation();
            if (rotation != 0) {
                canvas.saveState(); 
                canvas.concatCTM(
                    (float) Math.cos(Math.toRadians(rotation)),
                    (float) Math.sin(Math.toRadians(rotation)),
                    (float) -Math.sin(Math.toRadians(rotation)),
                    (float) Math.cos(Math.toRadians(rotation)),
                    x, y
                );
                x = 0;
                y = 0;
                
                canvas.beginText();
                canvas.setFontAndSize(baseFont, (float) textObj.getFontSize());
                canvas.setColorFill(textColor);
                canvas.setTextMatrix(x, y + (float) textObj.getFontSize());
                canvas.showText(textObj.getText());
                canvas.endText();
                
                canvas.restoreState(); 
            } else {
                canvas.beginText();
                canvas.setFontAndSize(baseFont, (float) textObj.getFontSize());
                canvas.setColorFill(textColor);
                canvas.setTextMatrix(x, y + (float) textObj.getFontSize());
                canvas.showText(textObj.getText());
                canvas.endText();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 按位置添加形状对象
     */
    private static void addShapeObjectWithPosition(PdfContentByte canvas, ShapeObject shapeObj, float x, float y, float width, float height) {
        try {
            canvas.saveState();
    
            // 设置线条和填充颜色
            if (shapeObj.getStrokeColor() != null) {
                Color strokeColor = Color.decode("#" + shapeObj.getStrokeColor());
                canvas.setColorStroke(new BaseColor(strokeColor.getRed(), strokeColor.getGreen(), strokeColor.getBlue()));
            }
            if (shapeObj.getFillColor() != null && !shapeObj.getFillColor().isEmpty()) {
                Color fillColor = Color.decode("#" + shapeObj.getFillColor());
                canvas.setColorFill(new BaseColor(fillColor.getRed(), fillColor.getGreen(), fillColor.getBlue()));
            }
            canvas.setLineWidth((float)shapeObj.getStrokeWidth());
            
            // 处理旋转
            double rotation = shapeObj.getRotation();
            if (rotation != 0) {
                canvas.saveState();
                float centerX = x + width / 2f;
                float centerY = y + height / 2f;
                canvas.concatCTM(
                    (float) Math.cos(Math.toRadians(rotation)),
                    (float) Math.sin(Math.toRadians(rotation)),
                    (float) -Math.sin(Math.toRadians(rotation)),
                    (float) Math.cos(Math.toRadians(rotation)),
                    centerX - centerX * (float) Math.cos(Math.toRadians(rotation)) + centerY * (float) Math.sin(Math.toRadians(rotation)),
                    centerY - centerX * (float) Math.sin(Math.toRadians(rotation)) - centerY * (float) Math.cos(Math.toRadians(rotation))
                );
            switch (shapeObj.getShapeType()) {
                case LINE:
                    canvas.moveTo(x, y + height);
                    canvas.lineTo(x + width, y);
                    canvas.stroke();
                    break;
                case RECTANGLE:
                    canvas.rectangle(x, y, width, height);
                    if (shapeObj.getFillColor() != null && !shapeObj.getFillColor().isEmpty()) {
                        canvas.fillStroke();
                    } else {
                        canvas.stroke();
                    }
                    break;
                case CIRCLE:
                    float radius = Math.min(width, height) / 2f;
                    centerX = x + radius;
                    centerY = y + radius;
                    canvas.ellipse(centerX + radius, centerY + radius, centerX - radius, centerY - radius);  // 宽高相等才是正圆
                    if (shapeObj.getFillColor() != null && !shapeObj.getFillColor().isEmpty()) {
                        canvas.fillStroke();
                    } else {
                        canvas.stroke();
                    }
                    break;
                case ELLIPSE:
                    float ellipseRadiusX = width / 2f;
                    float ellipseRadiusY = height / 2f;
                    float ellipseCenterX = x + ellipseRadiusX;
                    float ellipseCenterY = y + ellipseRadiusY;
                    canvas.ellipse(ellipseCenterX + ellipseRadiusX, ellipseCenterY + ellipseRadiusY, ellipseCenterX - ellipseRadiusX, ellipseCenterY - ellipseRadiusY);
                    if (shapeObj.getFillColor() != null && !shapeObj.getFillColor().isEmpty()) {
                        canvas.fillStroke();
                    } else {
                        canvas.stroke();
                    }
                    break;
                }
                canvas.restoreState();
            } else {
            switch (shapeObj.getShapeType()) {
                case LINE:
                    canvas.moveTo(x, y + height);
                    canvas.lineTo(x + width, y);
                    canvas.stroke();
                    break;
                case RECTANGLE:
                    canvas.rectangle(x, y, width, height);
                    if (shapeObj.getFillColor() != null && !shapeObj.getFillColor().isEmpty()) {
                        canvas.fillStroke();
                    } else {
                        canvas.stroke();
                    }
                    break;
                case CIRCLE:
                    float radius = Math.min(width, height) / 2f;
                    float centerX = x + radius;
                    float centerY = y + radius;
                    canvas.ellipse(centerX + radius, centerY - radius, centerX - radius, centerY + radius);  // 宽高相等才是正圆
                    if (shapeObj.getFillColor() != null && !shapeObj.getFillColor().isEmpty()) {
                        canvas.fillStroke();
                    } else {
                        canvas.stroke();
                    }
                    break;
                case ELLIPSE:
                    float ellipseRadiusX = width / 2f;
                    float ellipseRadiusY = height / 2f;
                    float ellipseCenterX = x + ellipseRadiusX;
                    float ellipseCenterY = y + ellipseRadiusY;
                    canvas.ellipse(ellipseCenterX + ellipseRadiusX, ellipseCenterY - ellipseRadiusY, ellipseCenterX - ellipseRadiusX, ellipseCenterY + ellipseRadiusY);
                    if (shapeObj.getFillColor() != null && !shapeObj.getFillColor().isEmpty()) {
                        canvas.fillStroke();
                    } else {
                        canvas.stroke();
                    }
                    break;
                }
            }
   
            canvas.restoreState();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 按位置添加图片对象
     */
    private static void addImageObjectWithPosition(Document document, PdfContentByte canvas, ImageObject imageObj, float x, float y, float width, float height) {
        try {
            String imagePath = imageObj.getImagePath();
            if (imagePath != null && new File(imagePath).exists()) {
                Image img = Image.getInstance(imagePath);
                
                // 设置图片大小
                img.scaleAbsolute(width, height);
                
                // 处理旋转
                double rotation = imageObj.getRotation();
                if (rotation != 0) {
                    canvas.saveState();
                    float centerX = x + width / 2f;
                    float centerY = y + height / 2f;
                    canvas.concatCTM(
                        (float) Math.cos(Math.toRadians(rotation)),
                        (float) Math.sin(Math.toRadians(rotation)),
                        (float) -Math.sin(Math.toRadians(rotation)),
                        (float) Math.cos(Math.toRadians(rotation)),
                        centerX - centerX * (float) Math.cos(Math.toRadians(rotation)) + centerY * (float) Math.sin(Math.toRadians(rotation)),
                        centerY - centerX * (float) Math.sin(Math.toRadians(rotation)) - centerY * (float) Math.cos(Math.toRadians(rotation))
                    );
                    img.setAbsolutePosition(x, y);
                    canvas.addImage(img);
                    canvas.restoreState();
                } else {
                    img.setAbsolutePosition(x, y);
                    canvas.addImage(img);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
