/*****************************************************************************
 * FVLCPlayerImpl.java FVLC VLC Java RMI Binding
 *****************************************************************************
 *
 * @author : Festastic, <info@festastic.com>
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *
 */

package com.festastic.fvlc.rmi;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

import org.videolan.jvlc.Audio;
import org.videolan.jvlc.JVLC;
import org.videolan.jvlc.LoggerVerbosityLevel;
import org.videolan.jvlc.MediaDescriptor;
import org.videolan.jvlc.MediaPlayer;
import org.videolan.jvlc.event.MediaPlayerListener;

import com.festastic.fvlc.util.VLCUtil;

public class FVLCPlayerImpl extends UnicastRemoteObject implements FVLCPlayer {

    private boolean         isInitialized = false;

    private JVLC            jvlc;
    private Audio           audio;
    private MediaPlayer     player;
    private MediaDescriptor descriptor;

    public FVLCPlayerImpl() throws RemoteException {
        super();
    }

    /**
     * Initializes JVLC instance and related Class instances.
     *
     * @param String
     *            abstract path
     * @throws RemoteException
     * @throws UnsatisfiedLinkError
     */
    public synchronized void init(String path) throws RemoteException, UnsatisfiedLinkError {
        jvlc = new JVLC(VLCUtil.getVLCInitArguments(path));

        jvlc.setLogVerbosity(LoggerVerbosityLevel.INFO);

        descriptor = new MediaDescriptor(jvlc, null);
        player = new MediaPlayer(descriptor);
        player.addListener(new FMediaPlayerListener());

        audio = jvlc.getAudio();

        notifyAll();

        isInitialized = true;
    }

    /**
     * Returns JVLC instance
     *
     * @return JVLC jvlc
     */
    public JVLC getVLC() {
        return jvlc;
    }

    public void play(String uri) throws RemoteException {
        waitForInitialize();
        try {
            descriptor.setMedia(uri);
            player.setMediaDescriptor(descriptor);
            player.play();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void stop() throws RemoteException {
        waitForInitialize();
        player.stop();
    }

    public void togglePause() throws RemoteException {
        waitForInitialize();
        player.pause();
    }

    public void seek(float position) throws RemoteException {
        waitForInitialize();
        player.setPosition(position);
    }

    public void setVolume(int volume) throws RemoteException {
        waitForInitialize();
        audio.setVolume(volume);
    }

    public boolean isPlaying() throws RemoteException {
        waitForInitialize();
        return player.isPlaying();
    }

    public float getPosition() throws RemoteException {
        waitForInitialize();
        return player.getPosition();
    }

    public boolean cachePosition() throws RemoteException {
        waitForInitialize();
        return player.cachePosition();
    }

    public void exit() throws RemoteException {
        System.exit(0);
    }

    /**
     * wait for initializing. for case if method is called remotely before
     * initialize done.
     */
    private synchronized void waitForInitialize() {
        if (!isInitialized) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private class FMediaPlayerListener implements MediaPlayerListener {
        public void endReached(MediaPlayer mediaplayer) {
        }

        public void errorOccurred(MediaPlayer mediaplayer) {
        }

        public void paused(MediaPlayer mediaplayer) {
        }

        public void playing(MediaPlayer mediaplayer) {
        }

        public void positionChanged(MediaPlayer mediaplayer) {
        }

        public void stopped(MediaPlayer mediaplayer) {
        }

        public void timeChanged(MediaPlayer mediaplayer, long l) {
        }
    }
}
