package at.oefai.aaa.animation;

import java.io.File;
import java.util.List;

import org.apache.batik.script.Window;
import org.w3c.dom.svg.SVGDocument;

import at.oefai.aaa.agent.jam.types.Value;

/**
 * BaseClass for all animations.
 * @author Stefan Rank
 */
abstract class AbstractBaseAnim implements BaseAnim {
    private static final long BASE_ANIM_INTERVAL = 100;
    protected long interval = BASE_ANIM_INTERVAL;
    private boolean firstTime = true;
    private Object timerTask;
    private Window scriptWindow;
    private File audio = null;
    private AudioThread audioThread = null;
    protected SVGDocument svgDoc = null;
    protected String actor = null;
    protected List<Value> args = null;

    public abstract boolean isFinished();

    protected abstract void doFirstTime();

    protected abstract void doIt();

    public abstract BaseAnim newInstance();

    public final void init(final SVGDocument pSvgDoc, final String pActor, final List<Value> pArgs) {
        this.svgDoc = pSvgDoc;
        this.actor = pActor;
        this.args = pArgs;
    }

    public final void start(final Window win, final File paudio) {
        assert win != null : "need scriptwindow for starting animation";
        this.scriptWindow = win;
        // using interval (though only for one call) because timeout gave odd errors
        this.timerTask = this.scriptWindow.setInterval(this, 1);
        assert this.timerTask != null : "didnt get timertask for unscheduling";
        this.audio = paudio;
    }

    public final void run() {
        if (this.timerTask != null) { // only if still a way to clear the task
            if (this.firstTime) {
                this.firstTime = false;
                doFirstTime();
                this.scriptWindow.clearInterval(this.timerTask);
                this.timerTask = this.scriptWindow.setInterval(this, this.interval);
                assert this.timerTask != null : "didnt get timertask for unscheduling";
                playSound();
            }
            doIt();
            if (isFinished()) {
                this.scriptWindow.clearInterval(this.timerTask);
                this.timerTask = null; // free reference
                stopSound();
                this.audioThread = null; // explicit freeing (not necessary)
            }
        }
    }

    protected final void playSound() {
        if (this.audioThread != null) {
            this.audioThread.playAsynchronousLoops(0);
        } else if (this.audio != null) {
            if (this.audio.exists()) {
                // create the thread here, it inherits priority
                // so probably the priority of the graphics thread
                this.audioThread = new AudioThread(this.audio);
                this.audioThread.playAsynchronousLoops(0);
            }
        }
    }

    private void stopSound() {
        if (this.audioThread != null) {
            this.audioThread.stopPlaying();
        }
    }

}
