/*

   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.EventQueue;
import java.awt.geom.AffineTransform;
import java.io.File;
import java.net.MalformedURLException;
import java.lang.ref.WeakReference;

import org.apache.batik.swing.gvt.GVTTreeRendererListener;
import org.apache.batik.swing.gvt.GVTTreeRendererEvent;
import org.apache.batik.swing.svg.SVGDocumentLoaderListener;
import org.apache.batik.swing.svg.SVGLoadEventDispatcherListener;
import org.apache.batik.swing.svg.SVGLoadEventDispatcherEvent;
import org.apache.batik.swing.svg.SVGDocumentLoaderEvent;
import org.apache.batik.swing.svg.GVTTreeBuilderListener;
import org.apache.batik.swing.svg.GVTTreeBuilderEvent;

import org.w3c.dom.svg.SVGDocument;

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

    public String getName() { return "JSVGInterruptTest."+getId(); }

    public JSVGInterruptTest() {
    }

    /* JSVGCanvasHandler.Delegate Interface */
    Runnable stopRunnable;

    int state = 0;
    MyLoaderListener  loadListener   = new MyLoaderListener();
    MyBuildListener   buildListener  = new MyBuildListener();
    MyOnloadListener  onloadListener = new MyOnloadListener();
    MyRenderListener  renderListener = new MyRenderListener();

    DelayRunnable stopper = null;


    static final int COMPLETE  = 1;
    static final int CANCELLED = 2;
    static final int FAILED    = 4;
    static final int MAX_WAIT  = 40000;

    public JSVGCanvasHandler createHandler() {
        return new JSVGCanvasHandler(this, this) {
                public void runCanvas(String desc) {
                    this.desc = desc;
                    setupCanvas();

                    if ( abort) return;
                    try {
                        synchronized (renderMonitor) {
                            delegate.canvasInit(canvas);
                            if ( abort) return;

                            while (!done) {
                                checkRender();
                                if ( abort) return;
                            }
                        }
                    } catch (Throwable t) {
                        t.printStackTrace();
                    } finally {
                        delegate.canvasDone(canvas);
                        dispose();
                    }
                }
                public void checkSomething(Object monitor, String errorCode) {
                    synchronized (monitor) {
                        try { monitor.wait(); }
                        catch(InterruptedException ie) { /* nothing */ }
                    }
                }
            };
    }


    public boolean canvasInit(final JSVGCanvas canvas) {
        // System.err.println("In Init");
        theCanvas = new WeakReference( canvas );
        theFrame  = handler.getFrame();
        registerObjectDesc(canvas, "JSVGCanvas");
        registerObjectDesc(handler.getFrame(), "JFrame");

        stopRunnable = new StopRunnable(canvas);

        File f = new File(getId());
        String uri;
        try {
            uri = f.toURL().toString();
        } catch (MalformedURLException mue) {
            throw new IllegalArgumentException(mue.getMessage());
        }

        tweakIt(canvas, uri);

        return false;
    }

    public void canvasDone(JSVGCanvas canvas) {
        loadListener   = null;
        buildListener  = null;
        renderListener = null;
        onloadListener = null;
        stopper        = null;
        stopRunnable   = null;
    }

    public void tweakIt(final JSVGCanvas canvas, final String uri) {
        Thread t = new Thread() {
                public void run() {
                    int state;
                    Runnable setURI = new Runnable() {
                            public void run() {
                                canvas.setURI(uri);
                            }
                        };
                    System.err.println("Starting Load Tweak");
                    canvas.addSVGDocumentLoaderListener(loadListener);
                    state = doTweak(setURI, loadListener);
                    canvas.removeSVGDocumentLoaderListener(loadListener);
                    System.err.println("Finished Load Tweak: " + state);

                    final SVGDocument doc = canvas.getSVGDocument();
                    Runnable setDoc = new Runnable() {
                            public void run() {
                                canvas.setSVGDocument(doc);
                            }
                        };
                    System.err.println("Starting setDoc Tweak");
                    canvas.addGVTTreeBuilderListener(buildListener);
                    state = doTweak(setDoc, buildListener);
                    canvas.removeGVTTreeBuilderListener(buildListener);
                    System.err.println("Finished setDoc Tweak: " + state);

                    if (canvas.isDynamic()) {
                        System.err.println("Starting onload Tweak");
                        canvas.addSVGLoadEventDispatcherListener
                            (onloadListener);
                        state = doTweak(setDoc, onloadListener);
                        canvas.removeSVGLoadEventDispatcherListener
                            (onloadListener);
                        System.err.println("Finished onload Tweak: " + state);
                    }

                    Runnable setTrans = new Runnable() {
                            public void run() {
                                canvas.setRenderingTransform
                                    (new AffineTransform(), true);
                            }
                        };
                    System.err.println("Starting render Tweak");
                    canvas.addGVTTreeRendererListener(renderListener);
                    state = doTweak(setTrans, renderListener);
                    canvas.removeGVTTreeRendererListener(renderListener);
                    System.err.println("Finished render Tweak: " + state);

                    handler.scriptDone();
                }
            };
        t.setDaemon(true);
        t.start();
    }

    public int doTweak(Runnable r, SetDelayable delayable) {
        synchronized (JSVGInterruptTest.this) {
            int delay = 0;
            int delayInc = 3;
            int delayIncInc = 4;
            int ret = 0;
            state = 0;
            while ((state & (COMPLETE | FAILED)) == 0) {
                ret |= state;
                state = 0;
                System.err.println("Tweaking: " + delay);
                delayable.setDelay(delay);
                EventQueue.invokeLater(r);

                long start = System.currentTimeMillis();
                long end   = start + MAX_WAIT;
                long curr  = start;
                while ((state == 0) && (curr < end)) {
                    // No 'complete' event generated yet and
                    // Still willing to wait a bit...
                    try {
                        JSVGInterruptTest.this.wait(end-curr);
                    } catch(InterruptedException ie) {
                    }
                    curr = System.currentTimeMillis();
                }
                if (state == 0) {
                    throw new IllegalArgumentException
                        ("Timed out - proabably indicates failure");
                }
                delay += delayInc + (curr-start-delay)/8;
                delayInc += delayIncInc;
            }
            ret |= state;
            return ret;
        }
    }


    public void triggerStopProcessing(int delay) {
        stopper = new DelayRunnable(delay, stopRunnable);
        stopper.start();
    }
    public boolean stopStopper() {
        return stopper.abort();
    }

    interface SetDelayable {
        void setDelay(int delay);
    }

    class MyLoaderListener implements SVGDocumentLoaderListener, SetDelayable {
        int delay = 0;
        public void setDelay(int delay) { this.delay = delay; }
        public void documentLoadingStarted(SVGDocumentLoaderEvent e) {
            triggerStopProcessing(delay);
        }
        public void documentLoadingCompleted(SVGDocumentLoaderEvent e) {
            stopStopper();
            synchronized (JSVGInterruptTest.this) {
                state |= COMPLETE;
                JSVGInterruptTest.this.notifyAll();
            }
        }
        public void documentLoadingCancelled(SVGDocumentLoaderEvent e) {
            synchronized (JSVGInterruptTest.this) {
                state |= CANCELLED;
                JSVGInterruptTest.this.notifyAll();
            }
        }
        public void documentLoadingFailed(SVGDocumentLoaderEvent e) {
            synchronized (JSVGInterruptTest.this) {
                state |= FAILED;
                JSVGInterruptTest.this.notifyAll();
            }
        }
    }

    class MyBuildListener implements GVTTreeBuilderListener, SetDelayable {
        int delay = 0;
        public void setDelay(int delay) { this.delay = delay; }
        public void gvtBuildStarted(GVTTreeBuilderEvent e) {
            // System.err.println("Build Start: " + e.getSource());
            triggerStopProcessing(delay);
        }
        public void gvtBuildCompleted(GVTTreeBuilderEvent e) {
            stopStopper();
            // System.err.println("Build Complete: " + e.getSource());
            synchronized (JSVGInterruptTest.this) {
                state |= COMPLETE;
                JSVGInterruptTest.this.notifyAll();
            }
        }
        public void gvtBuildCancelled(GVTTreeBuilderEvent e) {
            // System.err.println("Build Cancelled");
            synchronized (JSVGInterruptTest.this) {
                state |= CANCELLED;
                JSVGInterruptTest.this.notifyAll();
            }
        }
        public void gvtBuildFailed(GVTTreeBuilderEvent e) {
            // System.err.println("Build Failed");
            synchronized (JSVGInterruptTest.this) {
                state |= FAILED;
                JSVGInterruptTest.this.notifyAll();
            }
        }
    }

    class MyOnloadListener
        implements SVGLoadEventDispatcherListener, SetDelayable {
        int delay = 0;
        public void setDelay(int delay) { this.delay = delay; }
        public void svgLoadEventDispatchStarted
            (SVGLoadEventDispatcherEvent e) {
            // System.err.println("Onload Start: " + e.getSource());
                triggerStopProcessing(delay);
            }
            public void svgLoadEventDispatchCompleted
                (SVGLoadEventDispatcherEvent e) {
                stopStopper();
                // System.err.println("Onload Complete: " + e.getSource());
                synchronized (JSVGInterruptTest.this) {
                    state |= COMPLETE;
                    JSVGInterruptTest.this.notifyAll();
                }
            }
            public void svgLoadEventDispatchCancelled
                (SVGLoadEventDispatcherEvent e) {
                // System.err.println("Onload Cancelled");
                synchronized (JSVGInterruptTest.this) {
                    state |= CANCELLED;
                    JSVGInterruptTest.this.notifyAll();
                }
            }
            public void svgLoadEventDispatchFailed
                (SVGLoadEventDispatcherEvent e) {
                // System.err.println("Onload Failed");
                synchronized (JSVGInterruptTest.this) {
                    state |= FAILED;
                    JSVGInterruptTest.this.notifyAll();
                }
            }
        }

    class MyRenderListener implements GVTTreeRendererListener, SetDelayable {
            int delay = 0;
            public void setDelay(int delay) { this.delay = delay; }
            public void gvtRenderingPrepare(GVTTreeRendererEvent e) {
                // System.err.println("Render Prep");
                triggerStopProcessing(delay);
            }
            public void gvtRenderingStarted(GVTTreeRendererEvent e) {
                // System.err.println("Render Start");
            }
            public void gvtRenderingCompleted(GVTTreeRendererEvent e) {
                stopStopper();
                // System.err.println("Render Complete");
                synchronized (JSVGInterruptTest.this) {
                    state |= COMPLETE;
                    JSVGInterruptTest.this.notifyAll();
                }
            }
            public void gvtRenderingCancelled(GVTTreeRendererEvent e) {
                // System.err.println("Render Cancelled");
                synchronized (JSVGInterruptTest.this) {
                    state |= CANCELLED;
                    JSVGInterruptTest.this.notifyAll();
                }
            }
            public void gvtRenderingFailed(GVTTreeRendererEvent e) {
                // System.err.println("Render Failed");
                synchronized (JSVGInterruptTest.this) {
                    state |= FAILED;
                    JSVGInterruptTest.this.notifyAll();
                }
            }
        }


    static class StopRunnable implements Runnable {
        JSVGCanvas canvas;
        public StopRunnable(JSVGCanvas canvas) {
            this.canvas = canvas;
        }

        public void run() {
            if (EventQueue.isDispatchThread())
                canvas.stopProcessing();
            else
                EventQueue.invokeLater(this);
        }
    }


    /**
     * a Runnable is run after the given delay has elapsed.
     * A call to abort() can <i>prevent</i> the start of the Runable before it is
     * started - it does not abort after it started.
     */
    class DelayRunnable extends Thread {

        /**
         * delay in milliSeconds - must not change after creation.
         */
        private final int delay;

        /**
         * the Runnable to start - must not change after creation.
         */
        private final Runnable r;

        volatile boolean stop     = false;
        volatile boolean complete = false;

        /**
         * @param delay to wait before r is started in milliSeconds
         * @param r a Runnable to start after delay
         */
        DelayRunnable(int delay, Runnable r) {

            if ( delay < 0 ){
                throw new IllegalArgumentException("delay must be >= 0 ! is:" + delay );
            }
            if ( r == null ){
                throw new IllegalArgumentException("Runnable must not be null!");
            }

            this.delay = delay;
            this.r = r;
            setDaemon(true);
        }
        public boolean getComplete() { return complete; }

        public boolean abort() {
            synchronized (this) {
                if (complete) return false;
                stop = true;  return true;
            }
        }
        public void run() {
            long start = System.currentTimeMillis();
            long end   = start + delay;
            long curr  = start;
            while (curr < end) {
                try {
                    Thread.sleep(end-curr);
                } catch(InterruptedException ie) {
                }
                curr = System.currentTimeMillis();
            }
            synchronized (this) {
                if (stop) return;
                r.run();
                complete = true;
            }
        }
    }

}
