/*

   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.swing;

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.lang.ref.WeakReference;

import javax.swing.JFrame;

import org.apache.batik.test.DefaultTestReport;
import org.apache.batik.test.Test;
import org.apache.batik.test.TestReport;


import org.apache.batik.bridge.ScriptingEnvironment;
import org.apache.batik.bridge.UpdateManager;
import org.apache.batik.bridge.UpdateManagerEvent;
import org.apache.batik.bridge.UpdateManagerListener;
import org.apache.batik.script.Interpreter;
import org.apache.batik.script.InterpreterException;
import org.apache.batik.util.RunnableQueue;

import org.apache.batik.swing.gvt.GVTTreeRendererAdapter;
import org.apache.batik.swing.gvt.GVTTreeRendererEvent;
import org.apache.batik.swing.svg.SVGDocumentLoaderAdapter;
import org.apache.batik.swing.svg.SVGDocumentLoaderEvent;
import org.apache.batik.swing.svg.SVGLoadEventDispatcherAdapter;
import org.apache.batik.swing.svg.SVGLoadEventDispatcherEvent;
import org.apache.batik.swing.svg.SVGLoadEventDispatcher;

/**
 * One line Class Desc
 *
 * Complete Class Desc
 *
 * @author <a href="mailto:deweese@apache.org">l449433</a>
 * @version $Id$
 */
public class JSVGCanvasHandler {

    public interface Delegate {
        String getName();
        // Returns true if a load event was triggered.  In this case
        // the handler will wait for the load event to complete/fail.
        boolean canvasInit(JSVGCanvas canvas);
        void canvasLoaded(JSVGCanvas canvas);
        void canvasRendered(JSVGCanvas canvas);
        boolean canvasUpdated(JSVGCanvas canvas);
        void canvasDone(JSVGCanvas canvas);
        void failure(TestReport report);
    }

    public static final String REGARD_TEST_INSTANCE = "regardTestInstance";
    public static final String REGARD_START_SCRIPT =
        "try { regardStart(); } catch (er) {}";

    /**
     * Error when canvas can't load SVG file.
     * {0} The file/url that could not be loaded.
     */
    public static final String ERROR_CANNOT_LOAD_SVG =
        "JSVGCanvasHandler.message.error.could.not.load.svg";

    /**
     * Error when canvas can't render SVG file.
     * {0} The file/url that could not be rendered.
     */
    public static final String ERROR_SVG_RENDER_FAILED =
        "JSVGCanvasHandler.message.error.svg.render.failed";

    /**
     * Error when canvas can't peform render update SVG file.
     * {0} The file/url that could not be updated..
     */
    public static final String ERROR_SVG_UPDATE_FAILED =
        "JSVGCanvasHandler.message.error.svg.update.failed";

    /**
     * Entry describing the error
     */
    public static final String ENTRY_KEY_ERROR_DESCRIPTION
        = "JSVGCanvasHandler.entry.key.error.description";

    public static String fmt(String key, Object []args) {
        return TestMessages.formatMessage(key, args);
    }

    JFrame     frame = null;
    JSVGCanvas canvas = null;
    WeakReference updateManager = null;
    WindowListener wl = null;
    InitialRenderListener irl = null;
    LoadListener ll = null;
    SVGLoadEventListener sll = null;
    UpdateRenderListener url = null;

    boolean failed;
    boolean abort = false;
    boolean done  = false;

    final Object loadMonitor = new Object();

    final Object renderMonitor = new Object();

    Delegate delegate;
    Test host;
    String desc;

    public JSVGCanvasHandler(Test host, Delegate delegate) {
        this.host     = host;
        this.delegate = delegate;
    }

    public JFrame getFrame()     { return frame; }
    public JSVGCanvas getCanvas() { return canvas; }

    public JSVGCanvas createCanvas() { return new JSVGCanvas(); }

    public void runCanvas(String desc) {
        this.desc = desc;

        setupCanvas();

        if ( abort) return;

        try {
            synchronized (renderMonitor) {
                synchronized (loadMonitor) {
                    if (delegate.canvasInit(canvas)) {
                        checkLoad();
                    }
                }

                if ( abort) return;

                checkRender();
                if ( abort) return;

                if (updateManager == null || updateManager.get() == null)
                    return;

                while (!done) {
                    checkUpdate();
                    if ( abort) return;
                }
            }
        } catch (Throwable t) {
            t.printStackTrace();
        } finally {
            delegate.canvasDone(canvas);
            dispose();
        }
    }

    public void setupCanvas() {
        try {
            EventQueue.invokeAndWait(new Runnable() {
                    public void run() {
                        frame = new JFrame(delegate.getName());
                        canvas = createCanvas();
                        canvas.setPreferredSize(new Dimension(450, 500));
                        frame.getContentPane().add(canvas);
                        frame.pack();
                        wl = new WindowAdapter() {
                                public void windowClosing(WindowEvent e) {
                                    synchronized (loadMonitor) {
                                        abort = true;
                                        loadMonitor.notifyAll();
                                    }
                                    synchronized (renderMonitor) {
                                        abort = true;
                                        renderMonitor.notifyAll();
                                    }
                                }
                            };
                        frame.addWindowListener(wl);
                        frame.setVisible(true);

                        irl = new InitialRenderListener();
                        canvas.addGVTTreeRendererListener(irl);
                        ll = new LoadListener();
                        canvas.addSVGDocumentLoaderListener(ll);
                        sll = new SVGLoadEventListener();
                        canvas.addSVGLoadEventDispatcherListener(sll);

                    }});
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }


    public void scriptDone() {
        Runnable r = new Runnable() {
                public void run() {
                    UpdateManager um = getUpdateManager();
                    if (um != null)
                        um.forceRepaint();
                    synchronized(renderMonitor) {
                        done = true;
                        failed = false;
                        renderMonitor.notifyAll();
                    }
                }
            };
        UpdateManager um = getUpdateManager();
        if ((um == null) ||
            (!um.isRunning())){
            // Don't run it in this thread or we deadlock the event queue.
            Thread t = new Thread(r);
            t.start();
        } else {
            um.getUpdateRunnableQueue().invokeLater(r);
        }
    }

    public void dispose() {
        if (frame != null) {
            frame.removeWindowListener(wl);
            frame.setVisible(false);
        }
        wl = null;
        if (canvas != null) {
            canvas.removeGVTTreeRendererListener(irl);  irl=null;
            canvas.removeSVGDocumentLoaderListener(ll); ll=null;
            canvas.removeUpdateManagerListener(url);    url=null;
        }
        updateManager = null;
        canvas = null;
        frame = null;
    }

    public void checkSomething(Object monitor, String errorCode) {
        synchronized (monitor) {
            failed = true;
            try { monitor.wait(); }
            catch(InterruptedException ie) { /* nothing */ }
            if (abort || failed) {
                DefaultTestReport report = new DefaultTestReport(host);
                report.setErrorCode(errorCode);
                report.setDescription(new TestReport.Entry[] {
                    new TestReport.Entry
                    (fmt(ENTRY_KEY_ERROR_DESCRIPTION, null),
                     fmt(errorCode, new Object[]{desc}))
                });
                report.setPassed(false);
                delegate.failure(report);
                done = true;
                return;
            }
        }
    }

    public void checkLoad() {
        checkSomething(loadMonitor, ERROR_CANNOT_LOAD_SVG);
        delegate.canvasLoaded(canvas);
    }

    public void checkRender() {
        checkSomething(renderMonitor, ERROR_SVG_RENDER_FAILED);
        delegate.canvasRendered(canvas);
    }

    public void checkUpdate() {
        checkSomething(renderMonitor, ERROR_SVG_UPDATE_FAILED);
        if (!done)
            done = delegate.canvasUpdated(canvas);
    }

    public void bindHost() {
        UpdateManager um = getUpdateManager();
        RunnableQueue rq;
        rq = um.getUpdateRunnableQueue();
        rq.invokeLater(new Runnable() {
                UpdateManager um = getUpdateManager();
                public void run() {
                    ScriptingEnvironment scriptEnv;
                    scriptEnv = um.getScriptingEnvironment();
                    Interpreter interp;
                    interp    = scriptEnv.getInterpreter();
                    interp.bindObject(REGARD_TEST_INSTANCE,
                                      host);
                    try {
                        interp.evaluate(REGARD_START_SCRIPT);
                    } catch (InterpreterException ie) {
                        // Could not wait if no start script.
                    }
                }
            });
    }

    protected UpdateManager getUpdateManager() {
        if (updateManager != null) {
            return (UpdateManager) updateManager.get();
        }
        return null;
    }

    class UpdateRenderListener implements UpdateManagerListener {
        public void updateCompleted(UpdateManagerEvent e) {
            synchronized(renderMonitor){
                failed = false;
                renderMonitor.notifyAll();
            }
        }
        public void updateFailed(UpdateManagerEvent e) {
            synchronized(renderMonitor){
                renderMonitor.notifyAll();
            }
        }
        public void managerStarted(UpdateManagerEvent e) {
          bindHost();
        }
        public void managerSuspended(UpdateManagerEvent e) { }
        public void managerResumed(UpdateManagerEvent e) { }
        public void managerStopped(UpdateManagerEvent e) { }
        public void updateStarted(UpdateManagerEvent e) { }
    }

    class InitialRenderListener extends GVTTreeRendererAdapter {
        public void gvtRenderingCompleted(GVTTreeRendererEvent e) {
            synchronized(renderMonitor){
                failed = false;
                renderMonitor.notifyAll();
            }
        }


        public void gvtRenderingCancelled(GVTTreeRendererEvent e) {
            synchronized(renderMonitor){
                renderMonitor.notifyAll();
            }
        }

        public void gvtRenderingFailed(GVTTreeRendererEvent e) {
            synchronized(renderMonitor){
                renderMonitor.notifyAll();
            }
        }
    }

    class LoadListener extends SVGDocumentLoaderAdapter {
        public void documentLoadingCompleted(SVGDocumentLoaderEvent e) {
            synchronized(loadMonitor){
                failed = false;
                loadMonitor.notifyAll();
            }
        }

        public void documentLoadingFailed(SVGDocumentLoaderEvent e) {
            synchronized(loadMonitor){
                loadMonitor.notifyAll();
            }
        }

        public void documentLoadingCancelled(SVGDocumentLoaderEvent e) {
            synchronized(loadMonitor){
                loadMonitor.notifyAll();
            }
        }
    }

    class SVGLoadEventListener extends SVGLoadEventDispatcherAdapter {
        public void svgLoadEventDispatchStarted(SVGLoadEventDispatcherEvent e){
            SVGLoadEventDispatcher dispatcher;
            dispatcher = (SVGLoadEventDispatcher)e.getSource();
            UpdateManager um = dispatcher.getUpdateManager();
            updateManager = new WeakReference(um);
            url = new UpdateRenderListener();
            um.addUpdateManagerListener(url);
        }
    }

}
