package community.peers.internetradio.network;

import android.app.Activity;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.support.v4.app.NotificationCompat;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.android.volley.RequestQueue;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.Volley;

import org.videolan.libvlc.LibVLC;
import org.videolan.libvlc.Media;
import org.videolan.libvlc.MediaPlayer;

import java.util.ArrayList;
import java.util.HashMap;

import community.peers.internetradio.R;
import community.peers.internetradio.activity.MainActivity;
import community.peers.internetradio.broadcastintent.PlayPause;
import community.peers.internetradio.broadcastintent.Stop;
import community.peers.internetradio.storage.Settings;

public class Player {

    /**
     * This object represent a radio station.
     */
    protected static HashMap<String, String> radio;

    /**
     * libvlc instance.
     */
    protected static LibVLC vlc;

    /**
     * VLC Media Player.
     */
    protected static MediaPlayer player;

    /**
     * This object is created, then passed to the vlc player when a
     * new station is played. It represents a media to be played.
     * http://web.archive.org/web/20180413183729/https://code.videolan.org/videolan/vlc-android/blob/master/libvlc/src/org/videolan/libvlc/Media.java
     */
    protected static Media media_object;

    /**
     * Activity context.
     */
    protected static Activity context;

    /**
     * This function is called when a user clicks on a radio station.
     * The default action is to stop any open stream and play the new one.
     *
     * @param theContext
     * @param theRadio
     */
    public static void playStream (
        Activity theContext,
        HashMap<String, String> theRadio)
    {
        // Stop player if already playing another station
        Player.stop();

        context = theContext;
        radio = theRadio;

        Notification.setContext(context);

        // Initialize libvlc player
        final ArrayList<String> vlc_args = new ArrayList<>();
        // vlc_args.add("-vvv");
        vlc = new LibVLC (context, vlc_args);
        player = new MediaPlayer (vlc);

        if (radio == null || player == null)
            return;

        /**
         * Add events listener to the VLC player.
         */
        player.setEventListener (new MediaPlayer.EventListener () {
            @Override
            public void onEvent (MediaPlayer.Event event)
            {
            switch (event.type)
            {
                /**
                 * Change notification "Play" button to "Pause".
                 * The notification has 2 buttons "Play/Pause" and "Stop".
                 */
                case MediaPlayer.Event.Playing:
                    Notification.setPlaying();
                    break;

                /**
                 * Change notification "Pause" button to "Play".
                 * The notification has 2 buttons "Play/Pause" and "Stop".
                 */
                case MediaPlayer.Event.Stopped:
                    Notification.setStopped();
                    break;
            }
            }
        });

        // Show a notification for the new stream
        Notification.notifyNewStream(radio.get("name"));

        // Add media to VLC player and start streaming
        media_object = new Media (vlc, Uri.parse (radio.get ("stream")));

        // Add event listeners to detect changes in the metadata (song title)
        media_object.setEventListener (new Media.EventListener ()
        {
            @Override
            public void onEvent (Media.Event event)
            {
                // New metadata received
                if (event.type == Media.Event.MetaChanged)
                {
                    try {
                        Notification.updateStreamMetadata (
                            Player.player.getMedia().getMeta(Media.Meta.NowPlaying));
                    } catch (Exception e) {
                        Notification.updateStreamMetadata ("");
                    }
                }
            }
        });

        player.setMedia (Player.media_object);

        // Play stream immediately
        Player.play();
    }

    /**
     * Start playing stream.
     * Used when a new station is selected, or to resume a "Pause" action.
     */
    public static void play ()
    {
        if (player == null)
            return;

        player.play ();
    }

    /**
     * Pause media player.
     */
    public static void pause ()
    {
        if (player == null)
            return;

        /**
         * We actually stop() the player instead of pause()ing it.
         * The reason is that with pause(), what happens is
         *   - vlc keeps buffering stream
         *   - when play() again, it will resume where it was paused
         * We don't want this behavior for a live stream, what we want
         * is the current stream playing right now. So, simply stop the
         * player and restart it again later.
         */
        // player.pause ();
        player.stop ();
    }

    /**
     * Stop media player entirely.
     */
    public static void stop ()
    {
        if (player == null)
            return;

        Player.media_object.release();

        player.stop();
        player.release();
        player = null;

        Player.radio = null;
        Player.context = null;

        Notification.removeAll();
    }

    /**
     * Toggle player pause/play status.
     */
    public static void playOrPause ()
    {
        if (player == null)
            return;

        if (player.isPlaying ())
        {
            Player.pause ();

            // Change notification to display "Pause" message
            Notification.setPaused();
        } else {
            // Restart player
            Player.play ();

            // Resume fetching stream metadata
            Notification.notifyNewStream(radio.get("name"));
        }
    }
}