/*
 * File:     PlayerFactory.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.svg.SVGPrefs;

import mpi.eudico.server.corpora.clomimpl.abstr.MediaDescriptor;

import java.io.File;


/**
 * The PlayerFactory creates ElanMediaPlayers for a specific URL
 */
public class PlayerFactory {
    /** Holds value of property DOCUMENT ME! */
    public final static String JMF_MEDIA_FRAMEWORK = "JMF";

    /** Holds value of property DOCUMENT ME! */
    public final static String QT_MEDIA_FRAMEWORK = "QT";
    public static final String NATIVE_WINDOWS_MEDIA_FRAMEWORK = "NativeWindows";

    /**
     * The preferred call for client code to ask for an ElanMediaPlayer. Only
     * if the client code has a special reason to do so it should ask for a
     * specific media framework like QT or JMF. When there is more than one
     * media framework available the returned framework will be chosen as
     * follows: If the property preferredMF is defined and if the prefered
     * framework is available it will be chosen to construct a player. The
     * property is set by using java -DpreferredMFW="JMF" or
     * -DpreferredMFW="QT" Otherwise JMF is returned as the default preferred
     * framework. Of course if there is only one media framework available it
     * is chosen to construct the player. If the creation of the media players
     * failes a NoPlayerException is thrown
     *
     * @param mediaDescriptor DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     *
     * @throws NoPlayerException DOCUMENT ME!
     */
    public static ElanMediaPlayer createElanMediaPlayer(
        MediaDescriptor mediaDescriptor) throws NoPlayerException {
        // check if the media descriptor contains a valid media file reference
        String mediaURL = mediaDescriptor.mediaURL;

        if (mediaURL.startsWith("file")) {
            if (!new File(mediaURL.substring(5)).exists()) { // remove file: part of url string
                throw new NoPlayerException("Media File not found: " +
                    mediaURL);
            }
        } else if (mediaURL.startsWith("rtsp")) { // no test yet for rtsp media

            return createNativeMediaPlayerQT(mediaDescriptor);
        }

        String preferredMF = System.getProperty("PreferredMediaFramework");

        /*
         * gives fatal exceptions when quicktime is not installed

        int availableMF = DetectMediaFrameworks.getSupportedMediaFrameworksBitmap();

        if (preferredMF != null) {
            // Both audio and video are ok here, an exception will be thrown
            // if a video URL is used on an audio only JMF
            if (preferredMF.equals("JMF") &&
                    (((availableMF & DetectMediaFrameworks.JMF_AUDIO) |
                    (availableMF & DetectMediaFrameworks.JMF_VIDEO)) != 0)) {
                // try to create a JMF player
                return createJMFMediaPlayer(mediaDescriptor);
            } else if (preferredMF.equals("QT") &&
                    ((availableMF & DetectMediaFrameworks.QT_VIDEOAUDIO) != 0)) {
                // try to create a QT player
                return createQTMediaPlayer(mediaDescriptor);
            } else if (preferredMF.equals("NativeWindows")) {
                // try to create a NativeWindows player
                return createNativeMediaPlayer(mediaDescriptor);
            }
        }

        // If JMF is available return it as the default framework
        if (((availableMF & DetectMediaFrameworks.JMF_AUDIO) |
                (availableMF & DetectMediaFrameworks.JMF_VIDEO)) != 0) {
        //          return createJMFMediaPlayer(mediaDescriptor);
            return createNativeMediaPlayer(mediaDescriptor);

            //            return createQTMediaPlayer(mediaDescriptor);
        } else if ((availableMF & DetectMediaFrameworks.QT_VIDEOAUDIO) != 0) {
            return createQTMediaPlayer(mediaDescriptor);
        }

        */
        /* no longer necessary
        if (System.getProperty("os.name").toLowerCase().indexOf("unix") >= 0 ||
                System.getProperty("os.name").toLowerCase().indexOf("linux") >= 0) {
            return createJMFMediaPlayer(mediaDescriptor);
        }
        */
        try {
            // simplified version of the above
            if (preferredMF != null) {
                // Both audio and video are ok here, an exception will be thrown
                // if a video URL is used on an audio only JMF
                if (preferredMF.equals("JMF")) {
                    // try to create a JMF player
                    return createJMFMediaPlayer(mediaDescriptor);
                } else if (preferredMF.equals("QT")) {
                    // try to create a QT player
                    return createQTMediaPlayer(mediaDescriptor);
                } else if (preferredMF.equals("NativeWindows")) {
                    // try to create a NativeWindows player
                    return createNativeMediaPlayerDS(mediaDescriptor);

                    //return createNativeMediaPlayerQT(mediaDescriptor);
                    //return createQTMediaPlayer(mediaDescriptor);
                }
            }
        } catch (NoPlayerException npe) {
            System.out.println("Preferred media framework \'" + preferredMF +
                "\' can not handle: " + mediaDescriptor.mediaURL);
        }

        if (System.getProperty("os.name").toLowerCase().indexOf("windows") >= 0) {
            // at this point the preferred framework has already been tried
            ElanMediaPlayer player = null;

            if (!NATIVE_WINDOWS_MEDIA_FRAMEWORK.equals(preferredMF)) {
                try {
                    player = createNativeMediaPlayerDS(mediaDescriptor);
                } catch (NoPlayerException npe) {
                    System.out.println(npe.getMessage());
                }
            }

            if ((player == null) && !QT_MEDIA_FRAMEWORK.equals(preferredMF)) {
                try {
                    player = createQTMediaPlayer(mediaDescriptor);
                } catch (NoPlayerException npe) {
                    System.out.println("No QT: " + npe.getMessage());
                }
            }

            if ((player == null) && !JMF_MEDIA_FRAMEWORK.equals(preferredMF)) {
                try {
                    player = createJMFMediaPlayer(mediaDescriptor);
                } catch (NoPlayerException npe) {
                    System.out.println("No JMF: " + npe.getMessage());
                }
            }

            if (player != null) {
                return player;
            } else {
                throw new NoPlayerException(
                    "Could not create any media player for: " +
                    mediaDescriptor.mediaURL);
            }

            //return createNativeMediaPlayerDS(mediaDescriptor);
            //return createJMFMediaPlayer(mediaDescriptor);
        } else if (System.getProperty("os.name").toLowerCase().indexOf("os x") >= 0) {
            return createQTMediaPlayer(mediaDescriptor);
        }

        // always try as last possibility jmf
        // linux and unix get an JMFPlayer automatically
        return createJMFMediaPlayer(mediaDescriptor);
    }

    /**
     * Platform dependent media player
     *
     * @param mediaDescriptor
     * @return
     * @throws NoPlayerException
     */
    public static ElanMediaPlayer createNativeMediaPlayerDS(
        MediaDescriptor mediaDescriptor) throws NoPlayerException {
        if (System.getProperty("os.name").toLowerCase().indexOf("windows") >= 0) {
            System.out.println("Using Windows Native Media Player DS");

            return new NativeMediaPlayerWindowsDS(mediaDescriptor);

            //return new QTMediaPlayer(mediaDescriptor);
        } else {
            // no native framework available, throw an exception
            //throw new NoPlayerException("No Native Media Framework Available for " + System.getProperty("os.name"));
            // no native framework available, try jmf
            return createJMFMediaPlayer(mediaDescriptor);
        }
    }

    /**
     * Platform dependent media player
     *
     * @param mediaDescriptor
     * @return
     * @throws NoPlayerException
     */
    public static ElanMediaPlayer createNativeMediaPlayerQT(
        MediaDescriptor mediaDescriptor) throws NoPlayerException {
        if (System.getProperty("os.name").toLowerCase().indexOf("windows") >= 0) {
            System.out.println("Using Windows Native Media Player QT");

            return new NativeMediaPlayerWindowsQT(mediaDescriptor);
        } else {
            // no native framework available, throw an exception
            throw new NoPlayerException(
                "No Native Media Framework Available for " +
                System.getProperty("os.name"));
        }
    }

    /**
     *
     * @param mediaDescriptor
     * @return
     * @throws NoPlayerException
     */
    public static ElanMediaPlayer createJMFMediaPlayer(
        MediaDescriptor mediaDescriptor) throws NoPlayerException {
        System.out.println("Using JMF Media Player");

        //check if there is a .svg file in the descriptor
        if (SVGPrefs.getUseSVG()) {
            return new JMFGraphicMediaPlayer(mediaDescriptor);
        }

        return new JMFMediaPlayer(mediaDescriptor);
    }

    /**
     * Create a QT version of an ElanMediaPlayer for a certain URL
     *
     * @param mediaDescriptor DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     *
     * @throws NoPlayerException DOCUMENT ME!
     */
    public static ElanMediaPlayer createQTMediaPlayer(
        MediaDescriptor mediaDescriptor) throws NoPlayerException {
        // Look into Greg's PlayerFactory code for creating a QT player
        // JNLP needs to have the QTPlayer class explicitly loaded for some reason?
        System.out.println("Using QT Media Player");

        return new QTMediaPlayer(mediaDescriptor);

        //		throw new NoPlayerException("Unable to create a QT player");
    }
}
