/*

   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.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.lang.ref.SoftReference;

import org.apache.batik.anim.dom.AnimatedLiveAttributeValue;
import org.apache.batik.anim.dom.SVGOMAnimatedTransformList;
import org.apache.batik.anim.dom.SVGOMElement;
import org.apache.batik.css.engine.CSSEngineEvent;
import org.apache.batik.css.engine.SVGCSSEngine;
import org.apache.batik.dom.events.AbstractEvent;
import org.apache.batik.dom.svg.AbstractSVGTransformList;
import org.apache.batik.dom.svg.LiveAttributeException;
import org.apache.batik.dom.svg.SVGContext;
import org.apache.batik.dom.svg.SVGMotionAnimatableElement;
import org.apache.batik.ext.awt.geom.SegmentList;
import org.apache.batik.gvt.CanvasGraphicsNode;
import org.apache.batik.gvt.CompositeGraphicsNode;
import org.apache.batik.gvt.GraphicsNode;

import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.events.DocumentEvent;
import org.w3c.dom.events.EventTarget;
import org.w3c.dom.events.MutationEvent;
import org.w3c.dom.svg.SVGFitToViewBox;
import org.w3c.dom.svg.SVGTransformable;

/**
 * The base bridge class for SVG graphics node. By default, the namespace URI is
 * the SVG namespace. Override the <code>getNamespaceURI</code> if you want to add
 * custom <code>GraphicsNode</code> with a custom namespace.
 *
 * <p>This class handles various attributes that are defined on most
 * of the SVG graphic elements as described in the SVG
 * specification.</p>
 *
 * <ul>
 * <li>clip-path</li>
 * <li>filter</li>
 * <li>mask</li>
 * <li>opacity</li>
 * <li>transform</li>
 * <li>visibility</li>
 * </ul>
 *
 * @author <a href="mailto:tkormann@apache.org">Thierry Kormann</a>
 * @version $Id$
 */
public abstract class AbstractGraphicsNodeBridge extends AnimatableSVGBridge
    implements SVGContext,
               BridgeUpdateHandler,
               GraphicsNodeBridge,
               ErrorConstants {

    /**
     * The graphics node constructed by this bridge.
     */
    protected GraphicsNode node;

    /**
     * Whether the document is an SVG 1.2 document.
     */
    protected boolean isSVG12;

    /**
     * The unit context for length conversions.
     */
    protected UnitProcessor.Context unitContext;

    /**
     * Constructs a new abstract bridge.
     */
    protected AbstractGraphicsNodeBridge() {}

    /**
     * Creates a <code>GraphicsNode</code> according to the specified parameters.
     *
     * @param ctx the bridge context to use
     * @param e the element that describes the graphics node to build
     * @return a graphics node that represents the specified element
     */
    public GraphicsNode createGraphicsNode(BridgeContext ctx, Element e) {
        // 'requiredFeatures', 'requiredExtensions' and 'systemLanguage'
        if (!SVGUtilities.matchUserAgent(e, ctx.getUserAgent())) {
            return null;
        }

        GraphicsNode node = instantiateGraphicsNode();

        // 'transform'
        setTransform(node, e, ctx);

        // 'visibility'
        node.setVisible(CSSUtilities.convertVisibility(e));

        associateSVGContext(ctx, e, node);

        return node;
    }

    /**
     * Creates the GraphicsNode depending on the GraphicsNodeBridge
     * implementation.
     */
    protected abstract GraphicsNode instantiateGraphicsNode();

    /**
     * Builds using the specified BridgeContext and element, the
     * specified graphics node.
     *
     * @param ctx the bridge context to use
     * @param e the element that describes the graphics node to build
     * @param node the graphics node to build
     */
    public void buildGraphicsNode(BridgeContext ctx,
                                  Element e,
                                  GraphicsNode node) {
        // 'opacity'
        node.setComposite(CSSUtilities.convertOpacity(e));
        // 'filter'
        node.setFilter(CSSUtilities.convertFilter(e, node, ctx));
        // 'mask'
        node.setMask(CSSUtilities.convertMask(e, node, ctx));
        // 'clip-path'
        node.setClip(CSSUtilities.convertClipPath(e, node, ctx));
        // 'pointer-events'
        node.setPointerEventType(CSSUtilities.convertPointerEvents(e));

        initializeDynamicSupport(ctx, e, node);
    }

    /**
     * Returns true if the graphics node has to be displayed, false
     * otherwise.
     */
    public boolean getDisplay(Element e) {
        return CSSUtilities.convertDisplay(e);
    }

    /**
     * Returns an {@link AffineTransform} that is the transformation to
     * be applied to the node.
     */
    protected AffineTransform computeTransform(SVGTransformable te,
                                               BridgeContext ctx) {
        try {
            AffineTransform at = new AffineTransform();

            // 'transform'
            SVGOMAnimatedTransformList atl =
                (SVGOMAnimatedTransformList) te.getTransform();
            if (atl.isSpecified()) {
                atl.check();
                AbstractSVGTransformList tl =
                    (AbstractSVGTransformList) te.getTransform().getAnimVal();
                at.concatenate(tl.getAffineTransform());
            }

            // motion animation
            if (e instanceof SVGMotionAnimatableElement) {
                SVGMotionAnimatableElement mae = (SVGMotionAnimatableElement) e;
                AffineTransform mat = mae.getMotionTransform();
                if (mat != null) {
                    at.concatenate(mat);
                }
            }

            return at;
        } catch (LiveAttributeException ex) {
            throw new BridgeException(ctx, ex);
        }
    }

    /**
     * Sets the graphics node's transform to the current animated transform
     * value.
     */
    protected void setTransform(GraphicsNode n, Element e, BridgeContext ctx) {
        n.setTransform(computeTransform((SVGTransformable) e, ctx));
    }

    /**
     * Associates the {@link SVGContext} with the element.  This method should
     * be called even for static documents, since some bridges will need to
     * access animated attribute values even during the first build.
     */
    protected void associateSVGContext(BridgeContext ctx,
                                       Element e,
                                       GraphicsNode node) {
        this.e = e;
        this.node = node;
        this.ctx = ctx;
        this.unitContext = UnitProcessor.createContext(ctx, e);
        this.isSVG12 = ctx.isSVG12();
        ((SVGOMElement)e).setSVGContext(this);
    }

    /**
     * This method is invoked during the build phase if the document
     * is dynamic. The responsibility of this method is to ensure that
     * any dynamic modifications of the element this bridge is
     * dedicated to, happen on its associated GVT product.
     */
    protected void initializeDynamicSupport(BridgeContext ctx,
                                            Element e,
                                            GraphicsNode node) {
        if (ctx.isInteractive()) {
            // Bind the nodes for interactive and dynamic.
            ctx.bind(e, node);
        }
    }

    // BridgeUpdateHandler implementation //////////////////////////////////

    /**
     * Invoked when an MutationEvent of type 'DOMAttrModified' is fired.
     */
    public void handleDOMAttrModifiedEvent(MutationEvent evt) {
    }

    /**
     * Invoked when the geometry of a graphical element has changed.
     */
    protected void handleGeometryChanged() {
        node.setFilter(CSSUtilities.convertFilter(e, node, ctx));
        node.setMask(CSSUtilities.convertMask(e, node, ctx));
        node.setClip(CSSUtilities.convertClipPath(e, node, ctx));
        if (isSVG12) {
            if (!SVG_USE_TAG.equals(e.getLocalName())) {
                // ShapeChange events get fired only for basic shapes and paths.
                fireShapeChangeEvent();
            }
            fireBBoxChangeEvent();
        }
    }

    /**
     * Fires a ShapeChange event on the element this bridge is managing.
     */
    protected void fireShapeChangeEvent() {
        DocumentEvent d = (DocumentEvent) e.getOwnerDocument();
        AbstractEvent evt = (AbstractEvent) d.createEvent("SVGEvents");
        evt.initEventNS(SVG_NAMESPACE_URI,
                        "shapechange",
                        true,
                        false);
        try {
            ((EventTarget) e).dispatchEvent(evt);
        } catch (RuntimeException ex) {
            ctx.getUserAgent().displayError(ex);
        }
    }

    /**
     * Invoked when an MutationEvent of type 'DOMNodeInserted' is fired.
     */
    public void handleDOMNodeInsertedEvent(MutationEvent evt) {
        if (evt.getTarget() instanceof Element) {
            // Handle "generic" bridges.
            Element e2 = (Element)evt.getTarget();
            Bridge b = ctx.getBridge(e2);
            if (b instanceof GenericBridge) {
                ((GenericBridge) b).handleElement(ctx, e2);
            }
        }
    }

    /**
     * Invoked when an MutationEvent of type 'DOMNodeRemoved' is fired.
     */
    public void handleDOMNodeRemovedEvent(MutationEvent evt) {
        Node parent = e.getParentNode();
        if (parent instanceof SVGOMElement) {
            SVGContext bridge = ((SVGOMElement) parent).getSVGContext();
            if (bridge instanceof SVGSwitchElementBridge) {
                ((SVGSwitchElementBridge) bridge).handleChildElementRemoved(e);
                return;
            }
        }
        CompositeGraphicsNode gn = node.getParent();
        gn.remove(node);
        disposeTree(e);
    }

    /**
     * Invoked when an MutationEvent of type 'DOMCharacterDataModified'
     * is fired.
     */
    public void handleDOMCharacterDataModified(MutationEvent evt) {
    }

    /**
     * Disposes this BridgeUpdateHandler and releases all resources.
     */
    public void dispose() {
        SVGOMElement elt = (SVGOMElement)e;
        elt.setSVGContext(null);
        ctx.unbind(e);

        bboxShape = null;
    }

    /**
     * Disposes all resources related to the specified node and its subtree.
     */
    protected static void disposeTree(Node node) {
        disposeTree(node, true);
    }

    /**
     * Disposes all resources related to the specified node and its subtree,
     * and optionally removes the nodes' {@link SVGContext}.
     */
    protected static void disposeTree(Node node, boolean removeContext) {
        if (node instanceof SVGOMElement) {
            SVGOMElement elt = (SVGOMElement)node;
            SVGContext ctx = elt.getSVGContext();
            if (ctx instanceof BridgeUpdateHandler) {
                BridgeUpdateHandler h = (BridgeUpdateHandler) ctx;
                if (removeContext) {
                    elt.setSVGContext(null);
                }
                h.dispose();
            }
        }
        for (Node n = node.getFirstChild(); n != null; n = n.getNextSibling()) {
            disposeTree(n, removeContext);
        }
    }

    /**
     * Invoked when an CSSEngineEvent is fired.
     */
    public void handleCSSEngineEvent(CSSEngineEvent evt) {
        try {
            SVGCSSEngine eng = (SVGCSSEngine) evt.getSource();
            int[] properties = evt.getProperties();
            for (int idx : properties) {
                handleCSSPropertyChanged(idx);
                String pn = eng.getPropertyName(idx);
                fireBaseAttributeListeners(pn);
            }
        } catch (Exception ex) {
            ctx.getUserAgent().displayError(ex);
        }
    }

    /**
     * Invoked for each CSS property that has changed.
     */
    protected void handleCSSPropertyChanged(int property) {
        switch(property) {
        case SVGCSSEngine.VISIBILITY_INDEX:
            node.setVisible(CSSUtilities.convertVisibility(e));
            break;
        case SVGCSSEngine.OPACITY_INDEX:
            node.setComposite(CSSUtilities.convertOpacity(e));
            break;
        case SVGCSSEngine.FILTER_INDEX:
            node.setFilter(CSSUtilities.convertFilter(e, node, ctx));
            break;
        case SVGCSSEngine.MASK_INDEX:
            node.setMask(CSSUtilities.convertMask(e, node, ctx));
            break;
        case SVGCSSEngine.CLIP_PATH_INDEX:
            node.setClip(CSSUtilities.convertClipPath(e, node, ctx));
            break;
        case SVGCSSEngine.POINTER_EVENTS_INDEX:
            node.setPointerEventType(CSSUtilities.convertPointerEvents(e));
            break;
        case SVGCSSEngine.DISPLAY_INDEX:
            if (!getDisplay(e)) {
                // Remove the subtree.
                CompositeGraphicsNode parent = node.getParent();
                parent.remove(node);
                disposeTree(e, false);
            }
            break;
        }
    }

    /**
     * Invoked when the animated value of an animatable attribute has changed.
     */
    public void handleAnimatedAttributeChanged
            (AnimatedLiveAttributeValue alav) {
        if (alav.getNamespaceURI() == null
                && alav.getLocalName().equals(SVG_TRANSFORM_ATTRIBUTE)) {
            setTransform(node, e, ctx);
            handleGeometryChanged();
        }
    }

    /**
     * Invoked when an 'other' animation value has changed.
     */
    public void handleOtherAnimationChanged(String type) {
        if (type.equals("motion")) {
            setTransform(node, e, ctx);
            handleGeometryChanged();
        }
    }

    /**
     * Checks if the bounding box of the node has changed, and if so,
     * fires a bboxchange event on the element.
     */
    protected void checkBBoxChange() {
        if (e != null) {
            /*Rectangle2D oldBBox = bbox;
            Rectangle2D newBBox = getBBox();
            if (oldBBox != newBBox && newBBox != null) {
                if (oldBBox == null ||
                        oldBBox.getX() != bbox.getX()
                        || oldBBox.getY() != bbox.getY()
                        || oldBBox.getWidth() != bbox.getWidth()
                        || oldBBox.getHeight() != bbox.getHeight()) {*/
                    fireBBoxChangeEvent();
                /*}
            }*/
        }
    }

    /**
     * Fires an svg:bboxchange event on the element.
     */
    protected void fireBBoxChangeEvent() {
        DocumentEvent d = (DocumentEvent) e.getOwnerDocument();
        AbstractEvent evt = (AbstractEvent) d.createEvent("SVGEvents");
        evt.initEventNS(SVG_NAMESPACE_URI,
                        "RenderedBBoxChange",
                        true,
                        false);
        try {
            ((EventTarget) e).dispatchEvent(evt);
        } catch (RuntimeException ex) {
            ctx.getUserAgent().displayError(ex);
        }
    }

    // SVGContext implementation ///////////////////////////////////////////

    /**
     * Returns the size of a px CSS unit in millimeters.
     */
    public float getPixelUnitToMillimeter() {
        return ctx.getUserAgent().getPixelUnitToMillimeter();
    }

    /**
     * Returns the size of a px CSS unit in millimeters.
     * This will be removed after next release.
     * @see #getPixelUnitToMillimeter()
     */
    public float getPixelToMM() {
        return getPixelUnitToMillimeter();
    }

    protected SoftReference bboxShape = null;
    protected Rectangle2D bbox = null;

    /**
     * Returns the tight bounding box in current user space (i.e.,
     * after application of the transform attribute, if any) on the
     * geometry of all contained graphics elements, exclusive of
     * stroke-width and filter effects).
     */
    public Rectangle2D getBBox() {
        if (node == null) {
            return null;
        }
        Shape s = node.getOutline();

        if ((bboxShape != null) && (s == bboxShape.get())) return bbox;
        bboxShape = new SoftReference(s); // don't keep this live.
        bbox = null;
        if (s == null) return bbox;

        // SegmentList.getBounds2D gives tight BBox.
        SegmentList sl = new SegmentList(s);
        bbox = sl.getBounds2D();
        return bbox;
    }

    /**
     * Returns the transformation matrix from current user units
     * (i.e., after application of the transform attribute, if any) to
     * the viewport coordinate system for the nearestViewportElement.
     */
    public AffineTransform getCTM() {
        GraphicsNode gn = node;
        AffineTransform ctm = new AffineTransform();
        Element elt = e;
        while (elt != null) {
            if (elt instanceof SVGFitToViewBox) {
                AffineTransform at;
                if (gn instanceof CanvasGraphicsNode) {
                    at = ((CanvasGraphicsNode)gn).getViewingTransform();
                } else {
                    at = gn.getTransform();
                }
                if (at != null) {
                    ctm.preConcatenate(at);
                }
                break;
            }

            AffineTransform at = gn.getTransform();
            if (at != null)
                ctm.preConcatenate(at);

            elt = SVGCSSEngine.getParentCSSStylableElement(elt);
            gn = gn.getParent();
        }
        return ctm;
    }

    /**
     * Returns the display transform.
     */
    public AffineTransform getScreenTransform() {
        return ctx.getUserAgent().getTransform();
    }

    /**
     * Sets the display transform.
     */
    public void setScreenTransform(AffineTransform at) {
        ctx.getUserAgent().setTransform(at);
    }

    /**
     * Returns the global transformation matrix from the current
     * element to the root.
     */
    public AffineTransform getGlobalTransform() {
        return node.getGlobalTransform();
    }

    /**
     * Returns the width of the viewport which directly contains the
     * given element.
     */
    public float getViewportWidth() {
        return ctx.getBlockWidth(e);
    }

    /**
     * Returns the height of the viewport which directly contains the
     * given element.
     */
    public float getViewportHeight() {
        return ctx.getBlockHeight(e);
    }

    /**
     * Returns the font-size on the associated element.
     */
    public float getFontSize() {
        return CSSUtilities.getComputedStyle
            (e, SVGCSSEngine.FONT_SIZE_INDEX).getFloatValue();
    }
}
