package examples.report;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Iterator;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;

import de.vc.jfo.Document;
import de.vc.jfo.attributes.Background;
import de.vc.jfo.flow.ExternalGraphic;
import de.vc.jfo.pagination.SimplePageMaster;
import de.vc.jfo.report.FOReport;
import de.vc.report.Report;
import de.vc.report.ReportContext;
import de.vc.report.ReportException;
import de.vc.report.ReportStorage;
import de.vc.report.storages.FilterStorage;

public class WatermarkReportStorage extends FilterStorage{


  //---- attributes ------------------------------------------------------------

  private final static String PNG_IMAGE_TYPE = "image/png";
  private String watermark;

  //---- statics ---------------------------------------------------------------

  //---- constructors ----------------------------------------------------------

  public WatermarkReportStorage(ReportStorage storage) {
    super(storage);
  }

  //---- public ----------------------------------------------------------------

  public void storeReport(Report report,ReportContext ctx) throws ReportException{
    Document document = ((FOReport)report).getFODocument();
    Iterator pageMasters = document.getLayoutMasterSet().getPageMasters().iterator();
    while (pageMasters.hasNext()){
      Object ps = pageMasters.next();
      if (ps instanceof SimplePageMaster){
        Background bg = ( (SimplePageMaster) ps).getRegionBody().getBackground();
        bg.setImage(getWatermark());
        bg.setRepeatMode(Background.REPEAT_NONE);
      }
    }

    super.storeReport(report,ctx);
  }

  //---- protected -------------------------------------------------------------

  protected synchronized String getWatermark(){
    if (watermark==null)
      watermark = createWatermark();
    return watermark;
  }

  //---- package ---------------------------------------------------------------

  //---- private ---------------------------------------------------------------

  /**
   * Creates a dynamic graphic.
   * @return ExternalGraphic
   */
  private static String createWatermark() {
    final int imageWidth = 300;
    final int imageHeight = 300;

    // We use a simple buffered image
    BufferedImage image = new BufferedImage(imageWidth, imageHeight,
                                            BufferedImage.TYPE_INT_RGB);
    Graphics g = image.getGraphics();
    g.setColor(Color.white);
    g.fillRect(0, 0, imageWidth, imageHeight);

    g.setColor(new Color(224,224,224));
    for (int i = 0; i < 300; i+=10)
      g.drawLine(i,0,0,imageHeight-i);

    g.setColor(new Color(128,0,0));
    g.setFont(Font.decode("Arial").deriveFont(10f));
    g.drawString("Dynamically generated watermark",5,12);

    // encode image into PNG using javax.imageio
    byte[] png = createPNG(image);

    // we create a temporary external-graphics object to encode the image
    // to a URL with the data scheme
    ExternalGraphic foGraphic = new ExternalGraphic();

    // the image url looks like: url(data:image/png;base64,[image data])
    foGraphic.setSourceAsBase64Data(png, PNG_IMAGE_TYPE);

    return foGraphic.getSource();
  }



  /**
   * Creates a PNG from a buffered image using javax.imageio
   * @param image BufferedImage
   * @return byte[]
   */
  private static byte[] createPNG(BufferedImage image){
    Iterator writers = ImageIO.getImageWritersByMIMEType(PNG_IMAGE_TYPE);
    if (!writers.hasNext())
      throw new RuntimeException("Format "+PNG_IMAGE_TYPE+" not supported.");
    javax.imageio.ImageWriter writer = (javax.imageio.ImageWriter) writers.next();
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    try {
      ImageOutputStream imageOut = ImageIO.createImageOutputStream(baos);
      writer.setOutput(imageOut);
      writer.write(image);
      imageOut.close();
    }
    catch (IOException ex) {
      ex.printStackTrace();
    }
    return baos.toByteArray();
  }

  //---- inner classes ---------------------------------------------------------

}
