/*

   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.anim.timing;

import java.util.*;

import org.apache.batik.anim.AnimationException;
import org.apache.batik.i18n.LocalizableSupport;
import org.apache.batik.parser.ClockHandler;
import org.apache.batik.parser.ClockParser;
import org.apache.batik.parser.ParseException;
import org.apache.batik.util.SMILConstants;

import org.w3c.dom.Element;
import org.w3c.dom.events.Event;
import org.w3c.dom.events.EventTarget;

/**
 * An abstract base class for elements that can have timing applied to them.
 * The concrete versions of this class do not necessarily have to be the
 * same as the DOM class, and in fact, this will mostly be impossible unless
 * creating new DOM classes that inherit from these elements.
 *
 * @author <a href="mailto:cam%40mcc%2eid%2eau">Cameron McCormack</a>
 * @version $Id$
 */
public abstract class TimedElement implements SMILConstants {

    // Constants for fill mode.
    public static final int FILL_REMOVE = 0;
    public static final int FILL_FREEZE = 1;

    // Constants for restart mode.
    public static final int RESTART_ALWAYS          = 0;
    public static final int RESTART_WHEN_NOT_ACTIVE = 1;
    public static final int RESTART_NEVER           = 2;

    // Constants for time values.
    public static final float INDEFINITE = Float.POSITIVE_INFINITY;
    public static final float UNRESOLVED = Float.NaN;

    /**
     * The root time container.
     */
    protected TimedDocumentRoot root;

    /**
     * The parent time container.
     */
    protected TimeContainer parent;

    /**
     * Timing specifiers for the begin times of this element.
     */
    protected TimingSpecifier[] beginTimes;

    /**
     * Timing specifiers for the end times of this element.
     */
    protected TimingSpecifier[] endTimes;

    /**
     * Duration of this element, if {@link #durMedia} <code>= false</code>.
     * If unspecified, it will be {@link #UNRESOLVED}.
     */
    protected float simpleDur;

    /**
     * Whether the simple duration of this element should be equal
     * to the implicit duration.
     */
    protected boolean durMedia;

    /**
     * The number of repeats.  If unspecified, it will be
     * {@link #UNRESOLVED}.
     */
    protected float repeatCount;

    /**
     * The duration of repeats.  If unspecified, it will be
     * {@link #UNRESOLVED}.
     */
    protected float repeatDur;

    /**
     * The current repeat iteration.
     */
    protected int currentRepeatIteration;

    /**
     * The local active time of the last repeat.
     */
    protected float lastRepeatTime;

    /**
     * The fill mode for this element.  Uses the FILL_* constants
     * defined in this class.
     */
    protected int fillMode;

    /**
     * The restart mode for this element.  Uses the RESTART_* constants
     * defined in this class.
     */
    protected int restartMode;

    /**
     * The minimum active duration of this element.  If {@link #minMedia}
     * <code>= true</code>, it will be <code>0f</code>.
     */
    protected float min;

    /**
     * Whether the min value was specified as 'media'.
     */
    protected boolean minMedia;

    /**
     * The maximum active duration of this element.  If {@link #maxMedia}
     * <code>= true</code>, it will be {@link #INDEFINITE}.
     */
    protected float max;

    /**
     * Whether the max value was specified as 'media'.
     */
    protected boolean maxMedia;

    /**
     * Whether the element is currently active.
     */
    protected boolean isActive;

    /**
     * Whether the element is currently frozen.
     */
    protected boolean isFrozen;

    /**
     * The current time of this element in local active time.
     */
    protected float lastSampleTime;

    /**
     * The computed repeat duration of the element.
     */
    protected float repeatDuration;

    /**
     * List of begin InstanceTimes.
     */
    protected List beginInstanceTimes = new ArrayList();

    /**
     * List of end InstanceTimes.
     */
    protected List endInstanceTimes = new ArrayList();

    /**
     * The current Interval.
     */
    protected Interval currentInterval;

    /**
     * The end time of the previous interval, initially
     * {@link Float#NEGATIVE_INFINITY}.
     */
    protected float lastIntervalEnd;

    /**
     * List of previous intervals.
     */
    // protected LinkedList previousIntervals = new LinkedList();

    /**
     * The previous interval.
     */
    protected Interval previousInterval;

    /**
     * List of TimingSpecifiers on other elements that depend on this
     * element's begin times.
     */
    protected LinkedList beginDependents = new LinkedList();

    /**
     * List of TimingSpecifiers on other elements that depend on this
     * element's end times.
     */
    protected LinkedList endDependents = new LinkedList();

    /**
     * Whether the list of instance times should be checked to update
     * the current interval.
     */
    protected boolean shouldUpdateCurrentInterval = true;

    /**
     * Whether this timed element has parsed its timing attributes yet.
     */
    protected boolean hasParsed;

    /**
     * Map of {@link Event} objects to {@link HashSet}s of {@link
     * TimingSpecifier}s that caught them.
     */
    protected Map handledEvents = new HashMap();

    /**
     * Whether this timed element is currently being sampled.
     */
    protected boolean isSampling;

    /**
     * Whether an instance time update message has already been propagated to
     * this timed element.
     */
    protected boolean hasPropagated;

    /**
     * Creates a new TimedElement.
     */
    public TimedElement() {
        beginTimes = new TimingSpecifier[0];
        endTimes = beginTimes;
        simpleDur = UNRESOLVED;
        repeatCount = UNRESOLVED;
        repeatDur = UNRESOLVED;
        lastRepeatTime = UNRESOLVED;
        max = INDEFINITE;
        lastSampleTime = UNRESOLVED;
        lastIntervalEnd = Float.NEGATIVE_INFINITY;
    }

    /**
     * Returns the root time container of this timed element.
     */
    public TimedDocumentRoot getRoot() {
        return root;
    }

    /**
     * Returns the current active time of this element.
     */
    public float getActiveTime() {
        return lastSampleTime;
    }

    /**
     * Returns the current simple time of this element.
     */
    public float getSimpleTime() {
        return lastSampleTime - lastRepeatTime;
    }

    /**
     * Called by a TimingSpecifier of this element when a new
     * InstanceTime is created.  This will be in response to an event
     * firing, a DOM method being called or a new Instance being
     * created by a syncbase element.
     */
    protected float addInstanceTime(InstanceTime time, boolean isBegin) {
        // Trace.enter(this, "addInstanceTime", new Object[] { time, new Boolean(isBegin) } ); try {
        hasPropagated = true;
        List instanceTimes = isBegin ? beginInstanceTimes : endInstanceTimes;
        int index = Collections.binarySearch(instanceTimes, time);
        if (index < 0) {
            index = -(index + 1);
        }
        instanceTimes.add(index, time);
        shouldUpdateCurrentInterval = true;
        float ret;
        if (root.isSampling() && !isSampling) {
            ret = sampleAt(root.getCurrentTime(), root.isHyperlinking());
        } else {
            ret = Float.POSITIVE_INFINITY;
        }
        hasPropagated = false;
        root.currentIntervalWillUpdate();
        return ret;
        // } finally { Trace.exit(); }
    }

    /**
     * Called by a TimingSpecifier of this element when an InstanceTime
     * should be removed.  This will be in response to the pruning of an
     * Interval.
     */
    protected float removeInstanceTime(InstanceTime time, boolean isBegin) {
        // Trace.enter(this, "removeInstanceTime", new Object[] { time, new Boolean(isBegin) } ); try {
        hasPropagated = true;
        List instanceTimes = isBegin ? beginInstanceTimes : endInstanceTimes;
        int index = Collections.binarySearch(instanceTimes, time);
        for (int i = index; i >= 0; i--) {
            InstanceTime it = (InstanceTime) instanceTimes.get(i);
            if (it == time) {
                instanceTimes.remove(i);
                break;
            }
            if (it.compareTo(time) != 0) {
                break;
            }
        }
        int len = instanceTimes.size();
        for (int i = index + 1; i < len; i++) {
            InstanceTime it = (InstanceTime) instanceTimes.get(i);
            if (it == time) {
                instanceTimes.remove(i);
                break;
            }
            if (it.compareTo(time) != 0) {
                break;
            }
        }
        shouldUpdateCurrentInterval = true;
        float ret;
        if (root.isSampling() && !isSampling) {
            ret = sampleAt(root.getCurrentTime(), root.isHyperlinking());
        } else {
            ret = Float.POSITIVE_INFINITY;
        }
        hasPropagated = false;
        root.currentIntervalWillUpdate();
        return ret;
        // } finally { Trace.exit(); }
    }

    /**
     * Called by a TimingSpecifier of this element when an InstanceTime
     * has been updated.  This will be in response to a dependent
     * syncbase change.
     */
    protected float instanceTimeChanged(InstanceTime time, boolean isBegin) {
        // Trace.enter(this, "instanceTimeChanged", new Object[] { time, new Boolean(isBegin) } ); try {
        hasPropagated = true;
        shouldUpdateCurrentInterval = true;
        float ret;
        if (root.isSampling() && !isSampling) {
            ret = sampleAt(root.getCurrentTime(), root.isHyperlinking());
        } else {
            ret = Float.POSITIVE_INFINITY;
        }
        hasPropagated = false;
        return ret;
        // } finally { Trace.exit(); }
    }

    /**
     * Adds a dependent TimingSpecifier for this element.
     */
    protected void addDependent(TimingSpecifier dependent, boolean forBegin) {
        // Trace.enter(this, "addDependent", new Object[] { dependent, new Boolean(forBegin) } ); try {
        if (forBegin) {
            beginDependents.add(dependent);
        } else {
            endDependents.add(dependent);
        }
        // } finally { Trace.exit(); }
    }

    /**
     * Removes a dependent TimingSpecifier for this element.
     */
    protected void removeDependent(TimingSpecifier dependent,
                                   boolean forBegin) {
        // Trace.enter(this, "removeDependent", new Object[] { dependent, new Boolean(forBegin) } ); try {
        if (forBegin) {
            beginDependents.remove(dependent);
        } else {
            endDependents.remove(dependent);
        }
        // } finally { Trace.exit(); }
    }

    /**
     * Returns the simple duration time of this element.
     */
    public float getSimpleDur() {
        if (durMedia) {
            return getImplicitDur();
        } else if (isUnresolved(simpleDur)) {
            if (isUnresolved(repeatCount) && isUnresolved(repeatDur)
                    && endTimes.length > 0) {
                return INDEFINITE;
            }
            return getImplicitDur();
        } else {
            return simpleDur;
        }
    }

    /**
     * Returns whether the given time value is equal to the
     * {@link #UNRESOLVED} value.
     */
    public static boolean isUnresolved(float t) {
        return Float.isNaN(t);
    }

    /**
     * Returns the active duration time of this element.
     */
    public float getActiveDur(float B, float end) {
        float d = getSimpleDur();
        float PAD;
        if (!isUnresolved(end) && d == INDEFINITE) {
            PAD = minusTime(end, B);
            repeatDuration = minTime(max, maxTime(min, PAD));
            return repeatDuration;
        }

        float IAD;
        if (d == 0) {
            IAD = 0;
        } else {
            if (isUnresolved(repeatDur) && isUnresolved(repeatCount)) {
                IAD = d;
            } else {
                float p1 = isUnresolved(repeatCount)
                                ? INDEFINITE
                                : multiplyTime(d, repeatCount);
                float p2 = isUnresolved(repeatDur)
                                ? INDEFINITE
                                : repeatDur;
                IAD = minTime(minTime(p1, p2), INDEFINITE);
            }
        }
        if (isUnresolved(end) || end == INDEFINITE) {
            PAD = IAD;
        } else {
            PAD = minTime(IAD, minusTime(end, B));
        }
        repeatDuration = IAD;
        return minTime(max, maxTime(min, PAD));
    }

    /**
     * Subtracts one simple time from another.
     */
    protected float minusTime(float t1, float t2) {
        if (isUnresolved(t1) || isUnresolved(t2)) {
            return UNRESOLVED;
        }
        if (t1 == INDEFINITE || t2 == INDEFINITE) {
            return INDEFINITE;
        }
        return t1 - t2;
    }

    /**
     * Multiplies one simple time by n.
     */
    protected float multiplyTime(float t, float n) {
        if (isUnresolved(t) || t == INDEFINITE) {
            return t;
        }
        return t * n;
    }

    /**
     * Returns the minimum of two time values.
     */
    protected float minTime(float t1, float t2) {
        if (t1 == 0.0f || t2 == 0.0f) {
            return 0.0f;
        }
        if ((t1 == INDEFINITE || isUnresolved(t1))
                && t2 != INDEFINITE && !isUnresolved(t2)) {
            return t2;
        }
        if ((t2 == INDEFINITE || isUnresolved(t2))
                && t1 != INDEFINITE && !isUnresolved(t1)) {
            return t1;
        }
        if (t1 == INDEFINITE && isUnresolved(t2)
                || isUnresolved(t1) && t2 == INDEFINITE) {
            return INDEFINITE;
        }
        if (t1 < t2) {
            return t1;
        }
        return t2;
    }

    /**
     * Returns the maximum of two time values.
     */
    protected float maxTime(float t1, float t2) {
        if ((t1 == INDEFINITE || isUnresolved(t1))
                && t2 != INDEFINITE && !isUnresolved(t2)) {
            return t1;
        }
        if ((t2 == INDEFINITE || isUnresolved(t2))
                && t1 != INDEFINITE && !isUnresolved(t1)) {
            return t2;
        }
        if (t1 == INDEFINITE && isUnresolved(t2)
                || isUnresolved(t1) && t2 == INDEFINITE) {
            return UNRESOLVED;
        }
        if (t1 > t2) {
            return t1;
        }
        return t2;
    }

    /**
     * Returns the implicit duration of the element.  Currently, nested time
     * containers are not supported by SVG so this just returns
     * {@link #UNRESOLVED} by default.  This should be overriden in derived
     * classes that play media, since they will have an implicit duration.
     */
    protected float getImplicitDur() {
        return UNRESOLVED;
    }

    /**
     * Notifies dependents of a new interval.
     */
    protected float notifyNewInterval(Interval interval) {
        // Trace.enter(this, "notifyNewInterval", new Object[] { interval } ); try {
        float dependentMinTime = Float.POSITIVE_INFINITY;
        Iterator i = beginDependents.iterator();
        while (i.hasNext()) {
            TimingSpecifier ts = (TimingSpecifier) i.next();
            // Trace.print(ts.owner + "'s " + (ts.isBegin ? "begin" : "end" ) + ": " + ts);
            float t = ts.newInterval(interval);
            if (t < dependentMinTime) {
                dependentMinTime = t;
            }
        }
        i = endDependents.iterator();
        while (i.hasNext()) {
            TimingSpecifier ts = (TimingSpecifier) i.next();
            // Trace.print(ts.owner + "'s " + (ts.isBegin ? "begin" : "end" ) + ": " + ts);
            float t = ts.newInterval(interval);
            if (t < dependentMinTime) {
                dependentMinTime = t;
            }
        }
        return dependentMinTime;
        // } finally { Trace.exit(); }
    }

    /**
     * Notifies dependents of a removed interval.
     */
    protected float notifyRemoveInterval(Interval interval) {
        // Trace.enter(this, "notifyRemoveInterval", new Object[] { interval } ); try {
        float dependentMinTime = Float.POSITIVE_INFINITY;
        Iterator i = beginDependents.iterator();
        while (i.hasNext()) {
            TimingSpecifier ts = (TimingSpecifier) i.next();
            float t = ts.removeInterval(interval);
            if (t < dependentMinTime) {
                dependentMinTime = t;
            }
        }
        i = endDependents.iterator();
        while (i.hasNext()) {
            TimingSpecifier ts = (TimingSpecifier) i.next();
            float t = ts.removeInterval(interval);
            if (t < dependentMinTime) {
                dependentMinTime = t;
            }
        }
        return dependentMinTime;
        // } finally { Trace.exit(); }
    }

    /**
     * Calculates the local simple time.  Currently the hyperlinking parameter
     * is ignored, so DOM timing events are fired during hyperlinking seeks.
     * If we were following SMIL 2.1 rather than SMIL Animation, then these
     * events would have to be suppressed.
     *
     * @return the number of seconds until this element becomes active again
     *         if it currently is not, {@link Float#POSITIVE_INFINITY} if this
     *         element will become active at some undetermined point in the
     *         future (because of unresolved begin times, for example) or
     *         will never become active again, or <code>0f</code> if the
     *         element is currently active.
     */
    protected float sampleAt(float parentSimpleTime, boolean hyperlinking) {
        // Trace.enter(this, "sampleAt", new Object[] { Float.valueOf(parentSimpleTime) } ); try {
        isSampling = true;

        float time = parentSimpleTime; // No time containers in SVG.

        // First, process any events that occurred since the last sampling,
        // taking into account event sensitivity.
        for (Object o : handledEvents.entrySet()) {
            Map.Entry e = (Map.Entry) o;
            Event evt = (Event) e.getKey();
            Set ts = (Set) e.getValue();
            Iterator j = ts.iterator();
            boolean hasBegin = false, hasEnd = false;
            while (j.hasNext() && !(hasBegin && hasEnd)) {
                EventLikeTimingSpecifier t =
                        (EventLikeTimingSpecifier) j.next();
                if (t.isBegin()) {
                    hasBegin = true;
                } else {
                    hasEnd = true;
                }
            }
            boolean useBegin, useEnd;
            if (hasBegin && hasEnd) {
                useBegin = !isActive || restartMode == RESTART_ALWAYS;
                useEnd = !useBegin;
            } else if (hasBegin && (!isActive ||
                    restartMode == RESTART_ALWAYS)) {
                useBegin = true;
                useEnd = false;
            } else if (hasEnd && isActive) {
                useBegin = false;
                useEnd = true;
            } else {
                continue;
            }
            j = ts.iterator();
            while (j.hasNext()) {
                EventLikeTimingSpecifier t =
                        (EventLikeTimingSpecifier) j.next();
                boolean isBegin = t.isBegin();
                if (isBegin && useBegin || !isBegin && useEnd) {
                    t.resolve(evt);
                    shouldUpdateCurrentInterval = true;
                }
            }
        }
        handledEvents.clear();

        // Now process intervals.
        if (currentInterval != null) {
            float begin = currentInterval.getBegin();
            if (lastSampleTime < begin && time >= begin) {
                if (!isActive) {
                    toActive(begin);
                }
                isActive = true;
                isFrozen = false;
                lastRepeatTime = begin;
                fireTimeEvent
                    (SMIL_BEGIN_EVENT_NAME, currentInterval.getBegin(), 0);
            }
        }
        // For each sample, we might need to update the current interval's
        // begin and end times, or end the current interval and compute
        // a new one.
        boolean hasEnded = currentInterval != null
            && time >= currentInterval.getEnd();
        // Fire any repeat events that should have been fired since the
        // last sample.
        if (currentInterval != null) {
            float begin = currentInterval.getBegin();
            if (time >= begin) {
                float d = getSimpleDur();
                while (time - lastRepeatTime >= d
                        && lastRepeatTime + d < begin + repeatDuration) {
                    lastRepeatTime += d;
                    currentRepeatIteration++;
                    fireTimeEvent(root.getRepeatEventName(), lastRepeatTime,
                                  currentRepeatIteration);
                }
            }
        }

        // Trace.print("begin loop");
        float dependentMinTime = Float.POSITIVE_INFINITY;
        if (hyperlinking) {
            shouldUpdateCurrentInterval = true;
        }
        while (shouldUpdateCurrentInterval || hasEnded) {
            if (hasEnded) {
                // previousIntervals.add(currentInterval);
                previousInterval = currentInterval;
                isActive = false;
                isFrozen = fillMode == FILL_FREEZE;
                toInactive(false, isFrozen);
                fireTimeEvent(SMIL_END_EVENT_NAME, currentInterval.getEnd(), 0);
            }
            boolean first =
                // currentInterval == null && previousIntervals.isEmpty();
                currentInterval == null && previousInterval == null;
            if (currentInterval != null && hyperlinking) {
                // Hyperlinking, so remove the current interval and force a new
                // one to be computed.
                isActive = false;
                isFrozen = false;
                toInactive(false, false);
                currentInterval = null;
                // fireTimeEvent(SMIL_END_EVENT_NAME, currentInterval.getEnd(), 0);
            }
            if (currentInterval == null || hasEnded) {
                if (first || hyperlinking || restartMode != RESTART_NEVER) {
                    float beginAfter;
                    boolean incl = true;
                    if (first || hyperlinking) {
                        beginAfter = Float.NEGATIVE_INFINITY;
                    } else {
                        // beginAfter = ((Interval) previousIntervals.getLast()).getEnd();
                        beginAfter = previousInterval.getEnd();
                        incl = beginAfter != previousInterval.getBegin();
                    }
                    Interval interval =
                        computeInterval(first, false, beginAfter, incl);
                    if (interval == null) {
                        currentInterval = null;
                    } else {
                        float dmt = selectNewInterval(time, interval);
                        if (dmt < dependentMinTime) {
                            dependentMinTime = dmt;
                        }
                    }
                } else {
                    currentInterval = null;
                }
            } else {
                float currentBegin = currentInterval.getBegin();
                if (currentBegin > time) {
                    // Interval hasn't started yet.
                    float beginAfter;
                    boolean incl = true;
                    // if (previousIntervals.isEmpty()) {
                    if (previousInterval == null) {
                        beginAfter = Float.NEGATIVE_INFINITY;
                    } else {
                        // beginAfter = ((Interval) previousIntervals.getLast()).getEnd();
                        beginAfter = previousInterval.getEnd();
                        incl = beginAfter != previousInterval.getBegin();
                    }
                    Interval interval =
                        computeInterval(false, false, beginAfter, incl);
                    float dmt = notifyRemoveInterval(currentInterval);
                    if (dmt < dependentMinTime) {
                        dependentMinTime = dmt;
                    }
                    if (interval == null) {
                        currentInterval = null;
                    } else {
                        dmt = selectNewInterval(time, interval);
                        if (dmt < dependentMinTime) {
                            dependentMinTime = dmt;
                        }
                    }
                } else {
                    // Interval has already started.
                    Interval interval =
                        computeInterval(false, true, currentBegin, true);
                    float newEnd = interval.getEnd();
                    if (currentInterval.getEnd() != newEnd) {
                        float dmt =
                            currentInterval.setEnd
                                (newEnd, interval.getEndInstanceTime());
                        if (dmt < dependentMinTime) {
                            dependentMinTime = dmt;
                        }
                    }
                }
            }
            shouldUpdateCurrentInterval = false;
            hyperlinking = false;
            hasEnded = currentInterval != null && time >= currentInterval.getEnd();
        }
        // Trace.print("end loop");

        float d = getSimpleDur();
        if (isActive && !isFrozen) {
            if (time - currentInterval.getBegin() >= repeatDuration) {
                // Trace.print("element between repeat and active duration");
                isFrozen = fillMode == FILL_FREEZE;
                toInactive(true, isFrozen);
            } else {
                // Trace.print("element active, sampling at simple time " + (time - lastRepeatTime));
                sampledAt(time - lastRepeatTime, d, currentRepeatIteration);
            }
        }
        if (isFrozen) {
            float t;
            boolean atLast;
            if (isActive) {
                t = currentInterval.getBegin() + repeatDuration - lastRepeatTime;
                atLast = lastRepeatTime + d == currentInterval.getBegin() + repeatDuration;    // cam, given that d can
            } else {                                                                           // be infinite, nan or value
                // Interval previousInterval = (Interval) previousIntervals.getLast();         // does this always make sense?
                t = previousInterval.getEnd() - lastRepeatTime;                                // at least i would use >=
                atLast = lastRepeatTime + d == previousInterval.getEnd();                      // <- same here
            }
            if (atLast) {
                // Trace.print("element frozen" + (isActive ? " (but still active)" : "") + ", sampling last value");
                sampledLastValue(currentRepeatIteration);
            } else {
                // Trace.print("element frozen" + (isActive ? " (but still active)" : "") + ", sampling at simple time " + (t % d));
                sampledAt(t % d, d, currentRepeatIteration);
            }
        } else if (!isActive) {
            // Trace.print("element not sampling");
        }

        isSampling = false;

        lastSampleTime = time;
        if (currentInterval != null) {
            float t = currentInterval.getBegin() - time;
            if (t <= 0) {
                t = isConstantAnimation() || isFrozen ? currentInterval.getEnd() - time : 0;
            }
            if (dependentMinTime < t) {
                return dependentMinTime;
            }
            return t;
        }
        return dependentMinTime;
        // } finally { Trace.exit(); }
    }

    /**
     * Returns whether the end timing specifier list contains any eventbase,
     * accesskey or repeat timing specifiers.
     */
    protected boolean endHasEventConditions() {
        for (TimingSpecifier endTime : endTimes) {
            if (endTime.isEventCondition()) {
                return true;
            }
        }
        return false;
    }

    /**
     * Sets the current interval to the one specified.  This will notify
     * dependents and fire the 'begin' and any necessary 'repeat' events.
     * @param time the current sampling time
     * @param interval the Interval object to select to be current
     * @return the minimum time the animation engine can safely wait, as
     *         determined by dependents of the interval
     */
    protected float selectNewInterval(float time, Interval interval) {
        // Trace.enter(this, "selectNewInterval", new Object[] { interval }); try {
        currentInterval = interval;
        float dmt = notifyNewInterval(currentInterval);
        float beginEventTime = currentInterval.getBegin();
        if (time >= beginEventTime) {
            lastRepeatTime = beginEventTime;
            if (beginEventTime < 0) {
                beginEventTime = 0;
            }
            toActive(beginEventTime);
            isActive = true;
            isFrozen = false;
            fireTimeEvent(SMIL_BEGIN_EVENT_NAME, beginEventTime, 0);
            float d = getSimpleDur();
            float end = currentInterval.getEnd();
            while (time - lastRepeatTime >= d
                    && lastRepeatTime + d < end) {
                lastRepeatTime += d;
                currentRepeatIteration++;
                fireTimeEvent(root.getRepeatEventName(), lastRepeatTime,
                              currentRepeatIteration);
            }
        }
        return dmt;
        // } finally { Trace.exit(); }
    }

    /**
     * Computes an interval from the begin and end instance time lists.
     * @param first indicates whether this is the first interval to compute
     * @param fixedBegin if true, specifies that the value given for
     *                   <code>beginAfter</code> is taken to be the actual begin
     *                   time for the interval; only the end value is computed.
     * @param beginAfter the earliest possible begin time for the computed
     *                   interval.
     * @param incl if true (and <code>!fixedBegin</code>), specifies that the
     *             new interval's begin time must be greater than
     *             <code>beginAfter</code>; otherwise, the begin time must be
     *             greater than or equal to <code>beginAfter</code>.
     */
    protected Interval computeInterval(boolean first, boolean fixedBegin,
                                       float beginAfter, boolean incl) {
        // Trace.enter(this, "computeInterval", new Object[] { new Boolean(first), new Boolean(fixedBegin), Float.valueOf(beginAfter)} ); try {
        // Trace.print("computing interval from begins=" + beginInstanceTimes + ", ends=" + endInstanceTimes);
        Iterator beginIterator = beginInstanceTimes.iterator();
        Iterator endIterator = endInstanceTimes.iterator();
        float parentSimpleDur = parent.getSimpleDur();
        InstanceTime endInstanceTime = endIterator.hasNext()
            ? (InstanceTime) endIterator.next()
            : null;
        boolean firstEnd = true;
        InstanceTime beginInstanceTime = null;
        InstanceTime nextBeginInstanceTime = null;
        for (;;) {
            float tempBegin;
            if (fixedBegin) {
                tempBegin = beginAfter;
                while (beginIterator.hasNext()) {
                    nextBeginInstanceTime = (InstanceTime) beginIterator.next();
                    if (nextBeginInstanceTime.getTime() > tempBegin) {
                        break;
                    }
                }
            } else {
                for (;;) {
                    if (!beginIterator.hasNext()) {
                        // ran out of begin values
                        // Trace.print("returning null interval");
                        return null;
                    }
                    beginInstanceTime = (InstanceTime) beginIterator.next();
                    tempBegin = beginInstanceTime.getTime();
                    if (incl && tempBegin >= beginAfter
                            || !incl && tempBegin > beginAfter) {
                        if (beginIterator.hasNext()) {
                            nextBeginInstanceTime =
                                (InstanceTime) beginIterator.next();
                            if (beginInstanceTime.getTime()
                                    == nextBeginInstanceTime.getTime()) {
                                // XXX Not sure if this is exactly correct to
                                //     skip past these identical times, but it
                                //     avoids an infinite loop of 0s intervals
                                //     being created.
                                nextBeginInstanceTime = null;
                                continue;
                            }
                        }
                        break;
                    }
                }
            }
            if (tempBegin >= parentSimpleDur) {
                // the begin value is after the parent has ended
                // Trace.print("returning null interval");
                return null;
            }
            float tempEnd;
            if (endTimes.length == 0) {
                // no 'end' attribute specified
                tempEnd = tempBegin + getActiveDur(tempBegin, INDEFINITE);
                // Trace.print("no end specified, so tempEnd = " + tempEnd);
            } else {
                if (endInstanceTimes.isEmpty()) {
                    tempEnd = UNRESOLVED;
                } else {
                    tempEnd = endInstanceTime.getTime();
                    if (first && !firstEnd && tempEnd == tempBegin
                            || !first && currentInterval != null
                                && tempEnd == currentInterval.getEnd()
                                && (incl && beginAfter >= tempEnd
                                        || !incl && beginAfter > tempEnd)) {
                        for (;;) {
                            if (!endIterator.hasNext()) {
                                if (endHasEventConditions()) {
                                    tempEnd = UNRESOLVED;
                                    break;
                                }
                                // Trace.print("returning null interval");
                                return null;
                            }
                            endInstanceTime = (InstanceTime) endIterator.next();
                            tempEnd = endInstanceTime.getTime();
                            if (tempEnd > tempBegin) {
                                break;
                            }
                        }
                    }
                    firstEnd = false;
                    for (;;) {
                        if (tempEnd >= tempBegin) {
                            break;
                        }
                        if (!endIterator.hasNext()) {
                            if (endHasEventConditions()) {
                                tempEnd = UNRESOLVED;
                                break;
                            }
                            // Trace.print("returning null interval");
                            return null;
                        }
                        endInstanceTime = (InstanceTime) endIterator.next();
                        tempEnd = endInstanceTime.getTime();
                    }
                }
                float ad = getActiveDur(tempBegin, tempEnd);
                tempEnd = tempBegin + ad;
            }
            if (!first || tempEnd > 0 || tempBegin == 0 && tempEnd == 0
                    || isUnresolved(tempEnd)) {
                // Trace.print("considering restart semantics");
                if (restartMode == RESTART_ALWAYS
                        && nextBeginInstanceTime != null) {
                    float nextBegin = nextBeginInstanceTime.getTime();
                    // Trace.print("nextBegin == " + nextBegin);
                    if (nextBegin < tempEnd || isUnresolved(tempEnd)) {
                        tempEnd = nextBegin;
                        endInstanceTime = nextBeginInstanceTime;
                    }
                }
                Interval i = new Interval(tempBegin, tempEnd,
                                          beginInstanceTime, endInstanceTime);
                // Trace.print("returning interval: " + i);
                return i;
            }
            if (fixedBegin) {
                // Trace.print("returning null interval");
                return null;
            }
            beginAfter = tempEnd;
        }
        // } finally { Trace.exit(); }
    }

    /**
     * Resets this element.
     */
    protected void reset(boolean clearCurrentBegin) {
        Iterator i = beginInstanceTimes.iterator();
        while (i.hasNext()) {
            InstanceTime it = (InstanceTime) i.next();
            if (it.getClearOnReset() &&
                    (clearCurrentBegin
                        || currentInterval == null
                        || currentInterval.getBeginInstanceTime() != it)) {
                i.remove();
            }
        }
        i = endInstanceTimes.iterator();
        while (i.hasNext()) {
            InstanceTime it = (InstanceTime) i.next();
            if (it.getClearOnReset()) {
                i.remove();
            }
        }
        if (isFrozen) {
            removeFill();
        }
        currentRepeatIteration = 0;
        lastRepeatTime = UNRESOLVED;
        isActive = false;
        isFrozen = false;
        lastSampleTime = UNRESOLVED;
        // XXX should reconvert resolved syncbase/wallclock/media-marker time
        //     instances into the parent simple timespace
    }

    /**
     * Parses the animation attributes for this timed element.
     */
    public void parseAttributes(String begin, String dur, String end,
                                String min, String max, String repeatCount,
                                String repeatDur, String fill,
                                String restart) {
        if (!hasParsed) {
            parseBegin(begin);
            parseDur(dur);
            parseEnd(end);
            parseMin(min);
            parseMax(max);
            if (this.min > this.max) {
                this.min = 0f;
                this.max = INDEFINITE;
            }
            parseRepeatCount(repeatCount);
            parseRepeatDur(repeatDur);
            parseFill(fill);
            parseRestart(restart);
            hasParsed = true;
        }
    }

    /**
     * Parses a new 'begin' attribute.
     */
    protected void parseBegin(String begin) {
        try {
            if (begin.length() == 0) {
                begin = SMIL_BEGIN_DEFAULT_VALUE;
            }
            beginTimes = TimingSpecifierListProducer.parseTimingSpecifierList
                (TimedElement.this, true, begin,
                 root.useSVG11AccessKeys, root.useSVG12AccessKeys);
        } catch (ParseException ex) {
            throw createException
                ("attribute.malformed",
                 new Object[] { null, SMIL_BEGIN_ATTRIBUTE });
        }
    }

    /**
     * Parses a new 'dur' attribute.
     */
    protected void parseDur(String dur) {
        if (dur.equals(SMIL_MEDIA_VALUE)) {
            durMedia = true;
            simpleDur = UNRESOLVED;
        } else {
            durMedia = false;
            if (dur.length() == 0 || dur.equals(SMIL_INDEFINITE_VALUE)) {
                simpleDur = INDEFINITE;
            } else {
                try {
                    simpleDur = parseClockValue(dur, false);
                } catch (ParseException e) {
                    throw createException
                        ("attribute.malformed",
                         new Object[] { null, SMIL_DUR_ATTRIBUTE });
                }
                if (simpleDur < 0) {
                    simpleDur = INDEFINITE;
                }
            }
        }
    }

    /**
     * Parses a clock value or offset and returns it as a float.
     */
    protected float parseClockValue(String s, boolean parseOffset)
            throws ParseException {
        ClockParser p = new ClockParser(parseOffset);
        class Handler implements ClockHandler {
            protected float v = 0;
            public void clockValue(float newClockValue) {
                v = newClockValue;
            }
        }

        Handler h = new Handler();
        p.setClockHandler(h);
        p.parse(s);
        return h.v;
    }

    /**
     * Parses a new 'end' attribute.
     */
    protected void parseEnd(String end) {
        try {
            endTimes = TimingSpecifierListProducer.parseTimingSpecifierList
                (TimedElement.this, false, end,
                 root.useSVG11AccessKeys, root.useSVG12AccessKeys);
        } catch (ParseException ex) {
            throw createException
                ("attribute.malformed",
                 new Object[] { null, SMIL_END_ATTRIBUTE });
        }
    }

    /**
     * Parses a new 'min' attribute.
     */
    protected void parseMin(String min) {
        if (min.equals(SMIL_MEDIA_VALUE)) {
            this.min = 0;
            minMedia = true;
        } else {
            minMedia = false;
            if (min.length() == 0) {
                this.min = 0;
            } else {
                try {
                    this.min = parseClockValue(min, false);
                } catch (ParseException ex) {
                    this.min = 0;
                }
                if (this.min < 0) {
                    this.min = 0;
                }
            }
        }
    }

    /**
     * Parses a new 'max' attribute.
     */
    protected void parseMax(String max) {
        if (max.equals(SMIL_MEDIA_VALUE)) {
            this.max = INDEFINITE;
            maxMedia = true;
        } else {
            maxMedia = false;
            if (max.length() == 0 || max.equals(SMIL_INDEFINITE_VALUE)) {
                this.max = INDEFINITE;
            } else {
                try {
                    this.max = parseClockValue(max, false);
                } catch (ParseException ex) {
                    this.max = INDEFINITE;
                }
                if (this.max < 0) {
                    this.max = 0;
                }
            }
        }
    }

    /**
     * Parses a new 'repeatCount' attribute.
     */
    protected void parseRepeatCount(String repeatCount) {
        if (repeatCount.length() == 0) {
            this.repeatCount = UNRESOLVED;
        } else if (repeatCount.equals(SMIL_INDEFINITE_VALUE)) {
            this.repeatCount = INDEFINITE;
        } else {
            try {
                this.repeatCount = Float.parseFloat(repeatCount);
                if (this.repeatCount > 0) {
                    return;
                }
            } catch (NumberFormatException ex) {
                throw createException
                    ("attribute.malformed",
                     new Object[] { null, SMIL_REPEAT_COUNT_ATTRIBUTE });
            }
        }
    }

    /**
     * Parses a new 'repeatDur' attribute.
     */
    protected void parseRepeatDur(String repeatDur) {
        try {
            if (repeatDur.length() == 0) {
                this.repeatDur = UNRESOLVED;
            } else if (repeatDur.equals(SMIL_INDEFINITE_VALUE)) {
                this.repeatDur = INDEFINITE;
            } else {
                this.repeatDur = parseClockValue(repeatDur, false);
            }
        } catch (ParseException ex) {
            throw createException
                ("attribute.malformed",
                 new Object[] { null, SMIL_REPEAT_DUR_ATTRIBUTE });
        }
    }

    /**
     * Parses a new 'fill' attribute.
     */
    protected void parseFill(String fill) {
        if (fill.length() == 0 || fill.equals(SMIL_REMOVE_VALUE)) {
            fillMode = FILL_REMOVE;
        } else if (fill.equals(SMIL_FREEZE_VALUE)) {
            fillMode = FILL_FREEZE;
        } else {
            throw createException
                ("attribute.malformed",
                 new Object[] { null, SMIL_FILL_ATTRIBUTE });
        }
    }

    /**
     * Parses a new 'restart' attribute.
     */
    protected void parseRestart(String restart) {
        if (restart.length() == 0 || restart.equals(SMIL_ALWAYS_VALUE)) {
            restartMode = RESTART_ALWAYS;
        } else if (restart.equals(SMIL_WHEN_NOT_ACTIVE_VALUE)) {
            restartMode = RESTART_WHEN_NOT_ACTIVE;
        } else if (restart.equals(SMIL_NEVER_VALUE)) {
            restartMode = RESTART_NEVER;
        } else {
            throw createException
                ("attribute.malformed",
                 new Object[] { null, SMIL_RESTART_ATTRIBUTE });
        }
    }

    /**
     * Initializes this timed element.
     */
    public void initialize() {
        for (TimingSpecifier beginTime : beginTimes) {
            beginTime.initialize();
        }
        for (TimingSpecifier endTime : endTimes) {
            endTime.initialize();
        }
    }

    /**
     * Deinitializes this timed element.
     */
    public void deinitialize() {
        for (TimingSpecifier beginTime : beginTimes) {
            beginTime.deinitialize();
        }
        for (TimingSpecifier endTime : endTimes) {
            endTime.deinitialize();
        }
    }

    /**
     * Adds a time to the begin time instance list that will cause
     * the element to begin immediately (if restart semantics allow it).
     */
    public void beginElement() {
        beginElement(0);
    }

    /**
     * Adds a time to the begin time instance list that will cause
     * the element to begin at some offset to the current time (if restart
     * semantics allow it).
     */
    public void beginElement(float offset) {
        float t = root.convertWallclockTime( Calendar.getInstance());
        InstanceTime it = new InstanceTime(null, t + offset, true);
        addInstanceTime(it, true);
    }

    /**
     * Adds a time to the end time instance list that will cause
     * the element to end immediately (if restart semantics allow it).
     */
    public void endElement() {
        endElement(0);
    }

    /**
     * Adds a time to the end time instance list that will cause
     * the element to end at some offset to the current time (if restart
     * semantics allow it).
     */
    public void endElement(float offset) {
        float t = root.convertWallclockTime(Calendar.getInstance());
        InstanceTime it = new InstanceTime(null, t + offset, true);
        addInstanceTime(it, false);
    }

    /**
     * Returns the last sample time of this element, in local active time.
     */
    public float getLastSampleTime() {
        return lastSampleTime;
    }

    /**
     * Returns the begin time of the current interval, in parent simple time,
     * or <code>Float.NaN</code> if the element is not active.
     */
    public float getCurrentBeginTime() {
        float begin;
        if (currentInterval == null
                || (begin = currentInterval.getBegin()) < lastSampleTime) {
            return Float.NaN;
        }
        return begin;
    }

    /**
     * Returns whether this element can be begun or restarted currently.
     */
    public boolean canBegin() {
        return currentInterval == null
            || isActive && restartMode != RESTART_NEVER;
    }

    /**
     * Returns whether this element can be ended currently.
     */
    public boolean canEnd() {
        return isActive;
    }

    /**
     * Returns the time that the document would seek to if this animation
     * element were hyperlinked to, or <code>NaN</code> if there is no
     * such begin time.
     */
    public float getHyperlinkBeginTime() {
        if (isActive) {
            return currentInterval.getBegin();
        }
        if (!beginInstanceTimes.isEmpty()) {
            return ((InstanceTime) beginInstanceTimes.get(0)).getTime();
        }
        return Float.NaN;
    }

    /**
     * Returns an array of the begin timing specifiers on this timed element.
     * XXX Note that this is an experimental public API and is subject to
     * change, when somebody gets around to thinking of a better model for
     * exposing animation information from the document.
     */
    public TimingSpecifier[] getBeginTimingSpecifiers() {
        return (TimingSpecifier[]) beginTimes.clone();
    }

    /**
     * Returns an array of the end timing specifiers on this timed element.
     * XXX Note that this is an experimental public API and is subject to
     * change, when somebody gets around to thinking of a better model for
     * exposing animation information from the document.
     */
    public TimingSpecifier[] getEndTimingSpecifiers() {
        return (TimingSpecifier[]) endTimes.clone();
    }

    /**
     * Fires a TimeEvent of the given type on this element.
     * @param eventType the type of TimeEvent ("beginEvent", "endEvent"
     *                  or "repeatEvent").
     * @param time the timestamp of the event object
     * @param detail the repeat iteration, if this event is a repeat event
     */
    protected void fireTimeEvent(String eventType, float time, int detail) {
        Calendar t = (Calendar) root.getDocumentBeginTime().clone();
        t.add(Calendar.MILLISECOND, (int) Math.round(time * 1e3));
        fireTimeEvent(eventType, t, detail);
    }

    /**
     * Invoked by a {@link TimingSpecifier} to indicate that an event occurred
     * that would create a new instance time for this timed element.  These
     * will be processed at the beginning of the next tick.
     */
    void eventOccurred(TimingSpecifier t, Event e) {
        Set ts = (HashSet) handledEvents.get(e);
        if (ts == null) {
            ts = new HashSet();
            handledEvents.put(e, ts);
        }
        ts.add(t);
        root.currentIntervalWillUpdate();
    }

    /**
     * Fires a TimeEvent of the given type on this element.
     * @param eventType the type of TimeEvent ("beginEvent", "endEvent"
     *                  or "repeatEvent").
     * @param time the timestamp of the event object
     */
    protected abstract void fireTimeEvent(String eventType, Calendar time,
                                          int detail);

    /**
     * Invoked to indicate this timed element became active at the
     * specified time.
     * @param begin the time the element became active, in document simple time
     */
    protected abstract void toActive(float begin);

    /**
     * Invoked to indicate that this timed element became inactive.
     * @param stillActive if true, indicates that the element is still actually
     *                    active, but between the end of the computed repeat
     *                    duration and the end of the interval
     * @param isFrozen whether the element is frozen or not
     */
    protected abstract void toInactive(boolean stillActive, boolean isFrozen);

    /**
     * Invoked to indicate that this timed element has had its fill removed.
     */
    protected abstract void removeFill();

    /**
     * Invoked to indicate that this timed element has been sampled at the
     * given time.
     * @param simpleTime the sample time in local simple time
     * @param simpleDur the simple duration of the element
     * @param repeatIteration the repeat iteration during which the element
     *                        was sampled
     */
    protected abstract void sampledAt(float simpleTime, float simpleDur,
                                      int repeatIteration);

    /**
     * Invoked to indicate that this timed element has been sampled
     * at the end of its active time, at an integer multiple of the
     * simple duration.  This is the "last" value that will be used
     * for filling, which cannot be sampled normally.
     */
    protected abstract void sampledLastValue(int repeatIteration);

    /**
     * Returns the timed element with the given ID.
     */
    protected abstract TimedElement getTimedElementById(String id);

    /**
     * Returns the event target with the given ID.
     */
    protected abstract EventTarget getEventTargetById(String id);

    /**
     * Returns the event target that should be listened to for
     * access key events.
     */
    protected abstract EventTarget getRootEventTarget();

    /**
     * Returns the DOM element that corresponds to this timed element, if
     * such a DOM element exists.
     */
    public abstract Element getElement();

    /**
     * Returns the target of this animation as an {@link EventTarget}.  Used
     * for eventbase timing specifiers where the element ID is omitted.
     */
    protected abstract EventTarget getAnimationEventTarget();

    /**
     * Returns whether this timed element comes before the given timed element
     * in document order.
     */
    public abstract boolean isBefore(TimedElement other);

    /**
     * Returns whether this timed element is for a constant animation (i.e., a
     * 'set' animation.
     */
    protected abstract boolean isConstantAnimation();

    /**
     * Creates and returns a new {@link AnimationException}.
     */
    public AnimationException createException(String code, Object[] params) {
        Element e = getElement();
        if (e != null) {
            params[0] = e.getNodeName();
        }
        return new AnimationException(this, code, params);
    }

    /**
     * The error messages bundle class name.
     */
    protected static final String RESOURCES =
        "org.apache.batik.anim.resources.Messages";

    /**
     * The localizable support for the error messages.
     */
    protected static LocalizableSupport localizableSupport =
        new LocalizableSupport(RESOURCES, TimedElement.class.getClassLoader());

    /**
     * Implements {@link org.apache.batik.i18n.Localizable#setLocale(java.util.Locale)}.
     */
    public static void setLocale(Locale l) {
        localizableSupport.setLocale(l);
    }

    /**
     * Implements {@link org.apache.batik.i18n.Localizable#getLocale()}.
     */
    public static Locale getLocale() {
        return localizableSupport.getLocale();
    }

    /**
     * Implements {@link
     * org.apache.batik.i18n.Localizable#formatMessage(String,Object[])}.
     */
    public static String formatMessage(String key, Object[] args)
        throws MissingResourceException {
        return localizableSupport.formatMessage(key, args);
    }

    /**
     * Returns a string representation of the given time value.
     */
    public static String toString(float time) {
        if (Float.isNaN(time)) {
            return "UNRESOLVED";
        } else if (time == Float.POSITIVE_INFINITY) {
            return "INDEFINITE";
        } else {
            return Float.toString(time);
        }
    }
}
