/*
 * File:     EmptyMediaPlayer.java
 * Project:  MPI Linguistic Application
 * Date:     03 April 2006
 *
 * Copyright (C) 2001-2006  Max Planck Institute for Psycholinguistics
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package mpi.eudico.client.annotator.player;

import mpi.eudico.client.annotator.ElanLayoutManager;

import mpi.eudico.client.annotator.gui.FixedSizePanel;

import mpi.eudico.client.mediacontrol.ControllerEvent;
import mpi.eudico.client.mediacontrol.ControllerListener;
import mpi.eudico.client.mediacontrol.ControllerManager;
import mpi.eudico.client.mediacontrol.PeriodicUpdateController;
import mpi.eudico.client.mediacontrol.TimeEvent;


/**
 * The Empty implementation of an elan media player i.e. a MediaPlayer without
 * media
 */
public class EmptyMediaPlayer extends ControllerManager
    implements ElanMediaPlayer, ControllerListener {
    private long mediaTime;
    private long offset;
    private float rate;
    private float volume;
    private boolean playing;

    //private FixedSizePanel visualComponent;
    private long milliSecondsPerSample;
    private long duration;
    private long startTimeMillis;
    private boolean playingInterval;
    private PeriodicUpdateController periodicController;
    private long intervalStopTime;

    /**
     *
     *
     * @param duration DOCUMENT ME!
     */
    public EmptyMediaPlayer(long duration) {
        this.duration = duration;
        offset = 0;
        volume = 1;
        rate = 1;
        milliSecondsPerSample = 40;

        //visualComponent = new FixedSizePanel(200, 200);
    }

    public mpi.eudico.server.corpora.clomimpl.abstr.MediaDescriptor getMediaDescriptor() {
        return null;
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public String getFrameworkDescription() {
        return "Empty Media Player";
    }

    /**
     * Elan controllerUpdate Used to stop at the stop time in cooperation with
     * the playInterval method
     *
     * @param event DOCUMENT ME!
     */
    public synchronized void controllerUpdate(ControllerEvent event) {
        if (event instanceof TimeEvent) {
            if (periodicController != null) {
                if (getMediaTime() >= intervalStopTime) {
                    // stop the player
                    stop();
                }
            }
        }
    }

    /**
     * play between two times. This method uses the contollerUpdate method to
     * detect if the stop time is passed. The setStopTime method of JMF can
     * not be used because it gives unstable behaviour
     *
     * @param startTime DOCUMENT ME!
     * @param stopTime DOCUMENT ME!
     */
    public synchronized void playInterval(long startTime, long stopTime) {
        if (playingInterval || (stopTime <= startTime)) {
            return;
        }

        periodicController = new PeriodicUpdateController(25);
        periodicController.addControllerListener(this);
        addController(periodicController);
        intervalStopTime = stopTime;
        setMediaTime(startTime);
        playingInterval = true;
        start();
    }

    /**
     * Empty implementation for ElanMediaPlayer Interface
     * Only usefull for player that corectly supports setting stop time
     */
    public void setStopTime(long stopTime) {
    }

    /**
     * Disable all code for interval playing
     */
    private void stopPlayingInterval() {
        if (periodicController != null) {
            periodicController.removeControllerListener(this);
            removeController(periodicController);
            periodicController = null;
        }

        playingInterval = false;
    }

    /**
     * Gets the display Component for this Player.
     *
     * @return DOCUMENT ME!
     */
    public java.awt.Component getVisualComponent() {
        return null; //visualComponent;
    }

    /**
     * Gets the ratio between width and height of the video image
     *
     * @return DOCUMENT ME!
     */
    public float getAspectRatio() {
        return 1.0f;
    }

    /**
     * Starts the Player as soon as possible. is not synchronized in JMF
     */
    public synchronized void start() {
        playing = true;

        startTimeMillis = System.currentTimeMillis();

        // make sure all managed controllers are started
        startControllers();
    }

    /**
     * Stop the media player
     */
    public synchronized void stop() {
        if (playing) {
            mediaTime += (System.currentTimeMillis() - startTimeMillis);
        }

        playing = false;

        // make sure all managed controllers are stopped
        stopControllers();

        // make sure that all interval playing is finished
        if (playingInterval) {
            stopPlayingInterval();
        }
    }

    /**
     * Tell if this player is playing
     *
     * @return DOCUMENT ME!
     */
    public boolean isPlaying() {
        return playing;
    }

    /**
     * DOCUMENT ME!
     *
     * @return the step size for one frame
     */
    public long getMilliSecondsPerSample() {
        return milliSecondsPerSample;
    }

    /**
     * DOCUMENT ME!
     *
     * @param milliSeconds the step size for one frame
     */
    public void setMilliSecondsPerSample(long milliSeconds) {
        milliSecondsPerSample = milliSeconds;
    }

    /**
     * Set the offset to be used in get and set media time for this player
     *
     * @param offset the offset in milli seconds
     */
    public void setOffset(long offset) {
        this.offset = offset;
    }

    /**
     * DOCUMENT ME!
     *
     * @return the offset used by this player
     */
    public long getOffset() {
        return offset;
    }

    /**
     * Gets this Clock's current media time in milli seconds.
     *
     * @return DOCUMENT ME!
     */
    public long getMediaTime() {
        //System.out.println("Eget mt : " + (mediaTime - offset));
        if (playing) {
            return (mediaTime + System.currentTimeMillis()) - startTimeMillis;
        }

        return mediaTime - offset;
    }

    /**
     * Sets the Clock's media time in milli seconds. is not synchronized in JMF
     *
     * @param time DOCUMENT ME!
     */
    public void setMediaTime(long time) {
        //System.out.println("Eset mt : " + (time + offset));	
        mediaTime = time + offset;
        setControllersMediaTime(time);
    }

    public void nextFrame() {
        setMediaTime(getMediaTime() + getMilliSecondsPerSample());
    }

    public void previousFrame() {
        setMediaTime(getMediaTime() - getMilliSecondsPerSample());
    }

    /**
     * Gets the current temporal scale factor.
     *
     * @return DOCUMENT ME!
     */
    public float getRate() {
        return rate;
    }

    /**
     * Sets the temporal scale factor.
     *
     * @param rate DOCUMENT ME!
     */
    public synchronized void setRate(float rate) {
        this.rate = rate;
    }

    /**
     * Gets the volume as a number between 0 and 1
     *
     * @return DOCUMENT ME!
     */
    public float getVolume() {
        return volume;
    }

    /**
     * Gets the volume as a number between 0 and 1
     *
     * @param level DOCUMENT ME!
     */
    public void setVolume(float level) {
        volume = level;
    }

    /**
     * DOCUMENT ME!
     *
     * @param layoutManager DOCUMENT ME!
     */
    public void setLayoutManager(ElanLayoutManager layoutManager) {
    }

    /**
     * DOCUMENT ME!
     */
    public void updateLocale() {
    }

    /**
     * Get the duration of the media represented by this object in milli
     * seconds.
     *
     * @return DOCUMENT ME!
     */
    public long getMediaDuration() {
        return duration;
    }

    public void cleanUpOnClose() {
    }
}
