package com.huigou.bpm.management;

import com.mxgraph.canvas.mxGraphicsCanvas2D;
import com.mxgraph.canvas.mxICanvas2D;
import com.mxgraph.reader.mxSaxOutputHandler;
import com.mxgraph.util.mxUtils;
import com.mxpdf.text.Document;
import com.mxpdf.text.DocumentException;
import com.mxpdf.text.pdf.PdfWriter;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

import javax.imageio.ImageIO;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.io.StringReader;

/**
 * @author yonghuan
 */
public final class GraphUtils {

    private final static transient SAXParserFactory parserFactory = SAXParserFactory.newInstance();

    public static void writeImage(String format, int w, int h, Color bg, String xml, OutputStream os)
            throws IOException, SAXException, ParserConfigurationException {
        BufferedImage image = mxUtils.createBufferedImage(w, h, bg);
        if (image != null) {
            Graphics2D g2 = image.createGraphics();
            mxUtils.setAntiAlias(g2, true, true);
            renderXml(xml, createCanvas(g2));
            ImageIO.write(image, format, os);
        }
    }

    /**
     * @throws IOException
     * @throws DocumentException
     * @throws ParserConfigurationException
     * @throws SAXException
     */
    public static void writePdf(int w, int h, Color bg, String xml, OutputStream out)
            throws DocumentException, IOException, SAXException, ParserConfigurationException {
        // Fixes PDF offset
        w += 1;
        h += 1;

        Document document = new Document(new com.mxpdf.text.Rectangle(w, h));
        PdfWriter writer = PdfWriter.getInstance(document, out);
        document.open();

        mxGraphicsCanvas2D gc = createCanvas(writer.getDirectContent().createGraphics(w, h));

        // Fixes PDF offset
        gc.translate(1, 1);

        renderXml(xml, gc);
        gc.getGraphics().dispose();
        document.close();
        writer.flush();
    }

    /**
     * Renders the XML to the given canvas.
     */
    private static void renderXml(String xml, mxICanvas2D canvas) throws SAXException, ParserConfigurationException, IOException {
        XMLReader reader = parserFactory.newSAXParser().getXMLReader();
        reader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
        reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
        reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
        reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
        reader.setContentHandler(new mxSaxOutputHandler(canvas));
        reader.parse(new InputSource(new StringReader(xml)));
    }

    private static mxGraphicsCanvas2D createCanvas(Graphics2D g2) {
        mxGraphicsCanvas2D g2c = new mxGraphicsCanvas2D(g2);
        return g2c;
    }

}
