/*

   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to You under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

 */
package org.apache.batik.bridge;

import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.lang.ref.SoftReference;

import org.apache.batik.gvt.AbstractGraphicsNode;
import org.apache.batik.gvt.GraphicsNode;
import org.apache.batik.util.SVGConstants;
import org.w3c.dom.Element;

/**
 * RasterRable This is used to wrap a Rendered Image back into the
 * RenderableImage world.
 *
 * @author <a href="mailto:Thomas.DeWeese@Kodak.com">Thomas DeWeese</a>
 * @version $Id$
 */
public class MultiResGraphicsNode
    extends AbstractGraphicsNode implements SVGConstants {

    SoftReference [] srcs;
    Element       [] srcElems;
    Dimension     [] minSz;
    Dimension     [] maxSz;
    Rectangle2D      bounds;

    BridgeContext  ctx;

    Element multiImgElem;

    public MultiResGraphicsNode(Element multiImgElem,
                                Rectangle2D  bounds,
                                Element   [] srcElems,
                                Dimension [] minSz,
                                Dimension [] maxSz,
                                BridgeContext ctx) {

        this.multiImgElem = multiImgElem;
        this.srcElems     = new Element  [srcElems.length];
        this.minSz        = new Dimension[srcElems.length];
        this.maxSz        = new Dimension[srcElems.length];
        this.ctx          = ctx;

        for (int i=0; i<srcElems.length; i++) {
            this.srcElems[i] = srcElems[i];
            this.minSz[i]    = minSz[i];
            this.maxSz[i]    = maxSz[i];
        }

        this.srcs = new SoftReference[srcElems.length];
        this.bounds = bounds;
    }

    /**
     * Paints this node without applying Filter, Mask, Composite, and clip.
     *
     * @param g2d the Graphics2D to use
     */
    public void primitivePaint(Graphics2D g2d) {
        // get the current affine transform
        AffineTransform at = g2d.getTransform();

        double scx = Math.sqrt(at.getShearY()*at.getShearY()+
                               at.getScaleX()*at.getScaleX());
        double scy = Math.sqrt(at.getShearX()*at.getShearX()+
                               at.getScaleY()*at.getScaleY());

        GraphicsNode gn = null;
        int idx =-1;
        double w = bounds.getWidth()*scx;
        double minDist = calcDist(w, minSz[0], maxSz[0]);
        int    minIdx = 0;
        // System.err.println("Width: " + w);
        for (int i=0; i<minSz.length; i++) {
            double dist = calcDist(w, minSz[i], maxSz[i]);
            // System.err.println("Dist: " + dist);
            if (dist < minDist) {
                minDist = dist;
                minIdx = i;
            } 
                
            if (((minSz[i] == null) || (w >= minSz[i].width)) &&
                ((maxSz[i] == null) || (w <= maxSz[i].width))) {
                // We have a range match
                // System.err.println("Match: " + i + " " + 
                //                    minSz[i] + " -> " + maxSz[i]);
                if ((idx == -1) || (minIdx == i)) {
                    idx = i;
                }
            }
        }

        if (idx == -1)
            idx = minIdx;
        gn = getGraphicsNode(idx);
        if (gn == null) return;

        // This makes sure that the image 'pushes out' to it's pixel
        // bounderies.
        Rectangle2D gnBounds = gn.getBounds();
        if (gnBounds == null) return;

        double gnDevW = gnBounds.getWidth()*scx;
        double gnDevH = gnBounds.getHeight()*scy;
        double gnDevX = gnBounds.getX()*scx;
        double gnDevY = gnBounds.getY()*scy;
        double gnDevX0, gnDevX1, gnDevY0, gnDevY1;
        if (gnDevW < 0) {
            gnDevX0 = gnDevX+gnDevW;
            gnDevX1 = gnDevX;
        } else {
            gnDevX0 = gnDevX;
            gnDevX1 = gnDevX+gnDevW;
        }
        if (gnDevH < 0) {
            gnDevY0 = gnDevY+gnDevH;
            gnDevY1 = gnDevY;
        } else {
            gnDevY0 = gnDevY;
            gnDevY1 = gnDevY+gnDevH;
        }
        // This calculate the width/height in pixels given 'worst
        // case' assessment.
        gnDevW = (int)(Math.ceil(gnDevX1)-Math.floor(gnDevX0));
        gnDevH = (int)(Math.ceil(gnDevY1)-Math.floor(gnDevY0));
        scx = (gnDevW/gnBounds.getWidth())/scx;
        scy = (gnDevH/gnBounds.getHeight())/scy;

        // This scales things up slightly so our edges fall on device
        // pixel boundries.
        AffineTransform nat = g2d.getTransform();
        nat = new AffineTransform(nat.getScaleX()*scx, nat.getShearY()*scx,
                                 nat.getShearX()*scy, nat.getScaleY()*scy,
                                 nat.getTranslateX(), nat.getTranslateY());
        g2d.setTransform(nat);

        // double sx = bounds.getWidth()/sizes[idx].getWidth();
        // double sy = bounds.getHeight()/sizes[idx].getHeight();
        // System.err.println("Scale: [" + sx + ", " + sy + "]");

        gn.paint(g2d);
    }

    // This function can be tweaked to any extent.  This is a very
    // simple measure of 'goodness'.  It has two main flaws as is,
    // mostly in regards to distance calc with 'unbounded' ranges.
    // First it doesn't punish if the distance is the wrong way on the
    // unbounded range (so over a max by 10 is the same as under a max
    // by 10) this is compensated by the absolute preference for
    // matches 'in range' above.  The other issue is that unbounded
    // ranages tend to 'win' when the value is near the boundry point
    // since they use distance from the boundry point rather than the
    // middle of the range.  As it is this seems to meet all the
    // requirements of the SVG specification however.
    public double calcDist(double loc, Dimension min, Dimension max) {
        if (min == null) {
            if (max == null) 
                return 10E10; // very large number.
            else
                return Math.abs(loc-max.width);
        } else {
            if (max == null) 
                return Math.abs(loc-min.width);
            else {
                double mid = (max.width+min.width)/2.0;
                return Math.abs(loc-mid);
            }
        }
    }

    /**
     * Returns the bounds of the area covered by this node's primitive paint.
     */
    public Rectangle2D getPrimitiveBounds() {
        return bounds;
    }

    public Rectangle2D getGeometryBounds(){
        return bounds;
    }

    public Rectangle2D getSensitiveBounds(){
        return bounds;
    }

    /**
     * Returns the outline of this node.
     */
    public Shape getOutline() {
        return bounds;
    }

    public GraphicsNode getGraphicsNode(int idx) {
        if (srcs[idx] != null) {
            Object o = srcs[idx].get();
            if (o != null) 
                return (GraphicsNode)o;
        }
        
        try {
            GVTBuilder builder = ctx.getGVTBuilder();
            GraphicsNode gn;
            gn = builder.build(ctx, srcElems[idx]);
            srcs[idx] = new SoftReference(gn);
            return gn;
        } catch (Exception ex) { ex.printStackTrace();  }

        return null;
    }
}    

