/*

   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 org.apache.batik.gvt.CompositeGraphicsNode;
import org.apache.batik.gvt.GraphicsNode;
import org.apache.batik.gvt.RootGraphicsNode;
import org.apache.batik.util.HaltingThread;
import org.apache.batik.util.SVGConstants;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

/**
 * This class is responsible for creating a GVT tree using an SVG DOM tree.
 *
 * @author <a href="mailto:tkormann@apache.org">Thierry Kormann</a>
 * @version $Id$
 */
public class GVTBuilder implements SVGConstants {

    /**
     * Constructs a new builder.
     */
    public GVTBuilder() { }

    /**
     * Builds using the specified bridge context the specified SVG document.
     *
     * @param ctx the bridge context
     * @param document the SVG document to build
     * @exception BridgeException if an error occured while constructing
     * the GVT tree
     */
    public GraphicsNode build(BridgeContext ctx, Document document) {
        // the bridge context is now associated to one document
        ctx.setDocument(document);
        ctx.initializeDocument(document);

        // inform the bridge context the builder to use
        ctx.setGVTBuilder(this);

        // build the GVT tree
        DocumentBridge dBridge = ctx.getDocumentBridge();
        RootGraphicsNode rootNode = null;
        try {
            // create the root node
            rootNode = dBridge.createGraphicsNode(ctx, document);
            Element svgElement = document.getDocumentElement();
            GraphicsNode topNode = null;

            // get the appropriate bridge according to the specified element
            Bridge bridge = ctx.getBridge(svgElement);
            if (bridge == null || !(bridge instanceof GraphicsNodeBridge)) {
                return null;
            }
            // create the associated composite graphics node
            GraphicsNodeBridge gnBridge = (GraphicsNodeBridge)bridge;
            topNode = gnBridge.createGraphicsNode(ctx, svgElement);
            if (topNode == null) {
                return null;
            }
            rootNode.getChildren().add(topNode);

            buildComposite(ctx, svgElement, (CompositeGraphicsNode)topNode);
            gnBridge.buildGraphicsNode(ctx, svgElement, topNode);

            // finally, build the root node
            dBridge.buildGraphicsNode(ctx, document, rootNode);
        } catch (BridgeException ex) {
            // update the exception with the missing parameters
            ex.setGraphicsNode(rootNode);
            //ex.printStackTrace();
            throw ex; // re-throw the udpated exception
        }

        // For cursor handling
        if (ctx.isInteractive()) {
            ctx.addUIEventListeners(document);

            // register GVT listeners for AWT event support
            ctx.addGVTListener(document);
        }

        // <!> FIXME: TO BE REMOVED
        if (ctx.isDynamic()) {
            // register DOM listeners for dynamic support
            ctx.addDOMListeners();
        }
        return rootNode;
    }

    /**
     * Builds using the specified bridge context the specified Element.
     *
     * @param ctx the bridge context
     * @param e the element to build
     * @exception BridgeException if an error occured while constructing
     * the GVT tree
     */
    public GraphicsNode build(BridgeContext ctx, Element e) {
        // get the appropriate bridge according to the specified element
        Bridge bridge = ctx.getBridge(e);
        if (bridge instanceof GenericBridge) {
            // If it is a GenericBridge just handle it and any GenericBridge
            // descendents and return.
            ((GenericBridge) bridge).handleElement(ctx, e);
            handleGenericBridges(ctx, e);
            return null;
        } else if (bridge == null || !(bridge instanceof GraphicsNodeBridge)) {
            handleGenericBridges(ctx, e);
            return null;
        }
        // create the associated graphics node
        GraphicsNodeBridge gnBridge = (GraphicsNodeBridge)bridge;
        // check the display property
        if (!gnBridge.getDisplay(e)) {
            handleGenericBridges(ctx, e);
            return null;
        }
        GraphicsNode gn = gnBridge.createGraphicsNode(ctx, e);
        if (gn != null) {
            if (gnBridge.isComposite()) {
                buildComposite(ctx, e, (CompositeGraphicsNode)gn);
            } else {
                handleGenericBridges(ctx, e);
            }
            gnBridge.buildGraphicsNode(ctx, e, gn);
        }
        // <!> FIXME: see build(BridgeContext, Element)
        // + may load the script twice (for example
        // outside 'use' is ok versus local 'use' maybe wrong).
        if (ctx.isDynamic()) {
            //BridgeEventSupport.loadScripts(ctx, e);
        }
        return gn;
    }

    /**
     * Builds a composite Element.
     *
     * @param ctx the bridge context
     * @param e the element to build
     * @param parentNode the composite graphics node, parent of the
     *                   graphics node to build
     * @exception BridgeException if an error occured while constructing
     * the GVT tree
     */
    protected void buildComposite(BridgeContext ctx,
                                  Element e,
                                  CompositeGraphicsNode parentNode) {
        for (Node n = e.getFirstChild(); n != null; n = n.getNextSibling()) {
            if (n.getNodeType() == Node.ELEMENT_NODE) {
                buildGraphicsNode(ctx, (Element)n, parentNode);
            }
        }
    }

    /**
     * Builds a 'leaf' Element.
     *
     * @param ctx the bridge context
     * @param e the element to build
     * @param parentNode the composite graphics node, parent of the
     *                   graphics node to build
     * @exception BridgeException if an error occured while constructing
     * the GVT tree
     */
    protected void buildGraphicsNode(BridgeContext ctx,
                                     Element e,
                                     CompositeGraphicsNode parentNode) {
        // Check If we should halt early.
        if (HaltingThread.hasBeenHalted()) {
            throw new InterruptedBridgeException();
        }
        // get the appropriate bridge according to the specified element
        Bridge bridge = ctx.getBridge(e);
        if (bridge instanceof GenericBridge) {
            // If it is a GenericBridge just handle it and any GenericBridge
            // descendents and return.
            ((GenericBridge) bridge).handleElement(ctx, e);
            handleGenericBridges(ctx, e);
            return;
        } else if (bridge == null || !(bridge instanceof GraphicsNodeBridge)) {
            handleGenericBridges(ctx, e);
            return;
        }
        // check the display property
        if (!CSSUtilities.convertDisplay(e)) {
            handleGenericBridges(ctx, e);
            return;
        }
        GraphicsNodeBridge gnBridge = (GraphicsNodeBridge)bridge;
        try {
            // create the associated graphics node
            GraphicsNode gn = gnBridge.createGraphicsNode(ctx, e);
            if (gn != null) {
                // attach the graphics node to the GVT tree now !
                parentNode.getChildren().add(gn);
                // check if the element has children to build
                if (gnBridge.isComposite()) {
                    buildComposite(ctx, e, (CompositeGraphicsNode)gn);
                } else {
                    // if not then still handle the GenericBridges
                    handleGenericBridges(ctx, e);
                }
                gnBridge.buildGraphicsNode(ctx, e, gn);
            } else {
                handleGenericBridges(ctx, e);
            }
        } catch (BridgeException ex) {
            // some bridge may decide that the node in error can be
            // displayed (e.g. polyline, path...)
            // In this case, the exception contains the GraphicsNode
            GraphicsNode errNode = ex.getGraphicsNode();
            if (errNode != null) {
                parentNode.getChildren().add(errNode);
                gnBridge.buildGraphicsNode(ctx, e, errNode);
                ex.setGraphicsNode(null);
            }
            //ex.printStackTrace();
            throw ex;
        }
    }

    /**
     * Handles any GenericBridge elements which are children of the
     * specified element.
     * @param ctx the bridge context
     * @param e the element whose child elements should be handled
     */
    protected void handleGenericBridges(BridgeContext ctx, Element e) {
        for (Node n = e.getFirstChild(); n != null; n = n.getNextSibling()) {
            if (n instanceof Element) {
                Element e2 = (Element) n;
                Bridge b = ctx.getBridge(e2);
                if (b instanceof GenericBridge) {
                    ((GenericBridge) b).handleElement(ctx, e2);
                }
                handleGenericBridges(ctx, e2);
            }
        }
    }
}
