/*
 * Copyright
 *   2007 axYus - www.axyus.com
 *   2007 C.Marchand - christophe.marchand@axyus.com
 *
 * This file is part of XEMELIOS.
 *
 * XEMELIOS is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * XEMELIOS is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with XEMELIOS; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */



package fr.gouv.finances.cp.xemelios.ui.xhtmlviewer;

//~--- non-JDK imports --------------------------------------------------------

import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import org.apache.log4j.Logger;

import org.w3c.dom.Document;

import org.xhtmlrenderer.css.style.derived.RectPropertySet;
import org.xhtmlrenderer.event.DocumentListener;
import org.xhtmlrenderer.extend.UserAgentCallback;
import org.xhtmlrenderer.layout.Layer;
import org.xhtmlrenderer.layout.PaintingInfo;
import org.xhtmlrenderer.render.Box;
import org.xhtmlrenderer.render.RenderingContext;
import org.xhtmlrenderer.simple.XHTMLPanel;
import org.xhtmlrenderer.swing.Java2DOutputDevice;
import org.xhtmlrenderer.swing.ScalableXHTMLPanel;

//~--- JDK imports ------------------------------------------------------------

import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.print.PrinterGraphics;

import java.io.File;
import java.io.InputStream;

import java.util.ArrayList;

import javax.swing.JScrollPane;
import javax.swing.JViewport;

//~--- classes ----------------------------------------------------------------

/**
 *
 * @author chm
 */
public class XemeliosXhtmlPanel extends ScalableXHTMLPanel {
    private static final Logger logger = Logger.getLogger(XemeliosXhtmlPanel.class);
    private JInternalFrame iframe;
    private JFrame frame;

    //~--- fields -------------------------------------------------------------

//  public static final double SCALE_PAGE_WIDTH = -2.0d;
//  private double scale = -1.0d;
//  private Dimension lastLayoutSize=null;
//    private ArrayList<org.xhtmlrenderer.swing.ScaleChangeListener> listeners = null;

    //~--- constructors -------------------------------------------------------

    public XemeliosXhtmlPanel(UserAgentCallback uac, JInternalFrame frame) {
        super(uac);
        this.iframe=frame;
        addDocumentListener();
    }
    public XemeliosXhtmlPanel(UserAgentCallback uac, JFrame frame) {
        super(uac);
        this.frame=frame;
        addDocumentListener();
    }
//        listeners = new ArrayList<org.xhtmlrenderer.swing.ScaleChangeListener>();
    private void addDocumentListener() {
        addDocumentListener(new DocumentListener() {
            public void documentLoaded() {
                String url      = getURL().toExternalForm();
                int    sharpPos = url.indexOf('#');

                if (sharpPos >= 0) {
                    String anchorName = url.substring(sharpPos + 1);
                    Box    box        =
                        getSharedContext().getBoxById(anchorName);

                    if (box != null) {
                        Point pt;

                        if (box.getStyle().isInline()) {
                            pt = new Point(box.getAbsX(), box.getAbsY());
                        } else {
                            RectPropertySet margin =
                                box.getMargin(getLayoutContext());

                            pt = new Point(
                                box.getAbsX() + (int) margin.left(),
                                box.getAbsY() + (int) margin.top());
                        }

                        Point transPoint = new Point((int) (pt.getX()/ getScale()), (int) (pt.getY()/ getScale()));

                        scrollTo(transPoint);
                        repaint();

                        return;
                    } else {
                        logger.error("anchor not found: " + anchorName);
                    }
                }
                displayTitle(getDocumentTitle());
            }
            public void onLayoutException(Throwable throwable) {}
            public void onRenderException(Throwable throwable) {}
            public void documentStarted() {}
        });
    }

    public JInternalFrame getFrame() {
        return iframe;
    }
    protected void displayTitle(String title) {
        if(title!=null) {
            if(frame!=null) frame.setTitle(title);
            if(iframe!=null) iframe.setTitle(title);
        }
    }

    //~--- set methods --------------------------------------------------------

    public void setDocument(File file) throws Exception {
        setScalePolicy(SCALE_POLICY_FIT_WIDTH);
        super.setDocument(file);
    }

//  protected void calculateScale(Dimension layoutSize) {
//      Rectangle viewportBounds = getFixedRectangle();
//
//      if (viewportBounds.width < layoutSize.width) {
//          scale = (double)viewportBounds.width / layoutSize.width;
//      } else {
//          scale = 1.0d;
//      }
//  }
//  public double calculateScale() {
//      if(lastLayoutSize==null) return 1.0d;
//      double aScale;
//      Rectangle viewportBounds = getFixedRectangle();
//      if (viewportBounds.width < lastLayoutSize.width) {
//          aScale = (double)viewportBounds.width / lastLayoutSize.width;
//      } else {
//          aScale = 1.0d;
//      }
//      return aScale;
//  }

    /**
     * Force scale to use
     * @param newScale The scale to use
     * @throws IllegalArgumentException
     */
//  public void setScale(double newScale) throws IllegalArgumentException {
//      this.scale = newScale;
//      lastLayoutSize = null;
//      repaint(getFixedRectangle());
//      scaleChanged();
//  }
//  public void addScaleChangeListener(ScaleChangeListener scl) {
//      listeners.add(scl);
//  }
//  public void removeScaleChangeListener(ScaleChangeListener scl) {
//      listeners.remove(scl);
//  }
//  private void scaleChanged() {
//      ScaleChangeEvent evt = new ScaleChangeEvent(this,scale);
//      for(ScaleChangeListener scl:listeners) {
//          scl.scaleChanged(evt);
//      }
//  }
//  protected void doRender(RenderingContext c, Layer root) {
//      Graphics2D g = ((Java2DOutputDevice)c.getOutputDevice()).getGraphics();
//      if (!(g instanceof PrinterGraphics) && isOpaque()) {
//          g.setColor(getBackground());
//          g.fillRect(0, 0, getWidth(), getHeight());
//      }
//      AffineTransform current = g.getTransform();
//
//      PaintingInfo pI = root.getMaster().getPaintingInfo();
//      Dimension layoutSize = pI.getOuterMarginCorner();
//
//      if(-1.0d==scale) {
//          calculateScale(layoutSize);
//          scaleChanged();
//      }
//
//      if(lastLayoutSize==null) {
//          lastLayoutSize=layoutSize;
//          setSize((int)(lastLayoutSize.width*scale),(int)(lastLayoutSize.height*scale));
//      }
//
//      g.transform(AffineTransform.getScaleInstance(scale, scale));
//      super.doRender(c, root);
//      g.setTransform(current);
//  }
//  public Dimension getPreferredSize() { return getSize(); }
//  public Dimension getMinimumSize() { return getSize(); }
//  public Dimension getMaximumSize() { return getSize(); }
//  public Box find(int x, int y) {
//      int tX = (int)(x / scale);
//      int tY = (int)(y / scale);
//      Layer l = getRootLayer();
//      if (l != null) {
//          return l.find(layout_context, tX, tY);
//      }
//      return null;
//  }
    public void setDocument(Document doc, String url) {
        setScalePolicy(SCALE_POLICY_FIT_WIDTH);
        super.setDocument(doc, url);
    }

    public void setDocument(InputStream stream, String url) throws Exception {
        setScalePolicy(SCALE_POLICY_FIT_WIDTH);
        super.setDocument(stream, url);
    }
}

