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.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 community.peers.internetradio.R;
import community.peers.internetradio.activity.MainActivity;
import community.peers.internetradio.broadcastintent.PlayPause;
import community.peers.internetradio.broadcastintent.Stop;

public class Notification {
    /**
     * Needed when we receive actions occurring in the notification
     * player (via BroadcastIntent). This identify the notification.
     */
    protected static final int NOTIFICATION_ID = 0;

    /**
     * Truncate ticker message to this length.
     * The reason is that if it's too long, the user will receive
     * an excessively long notification in the status bar.
     */
    protected static final int TICKER_MAX_LENGTH = 100;

    /**
     * The "Now playing" bar under the toolbar.
     */
    protected static LinearLayout nowplaying;
    protected static TextView nowplaying_station;
    protected static TextView nowplaying_steam_metadata;

    /**
     * The notification that will be displayed in the notification drawer.
     */
    protected static NotificationCompat.Builder streamNotification;

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

    public static void setContext(Activity context) {
        Notification.context = context;

        Notification.nowplaying = (LinearLayout) context.findViewById(R.id.playing_info);
        Notification.nowplaying_station = (TextView) context.findViewById(R.id.playing_station_name);
        Notification.nowplaying_steam_metadata = (TextView) context.findViewById(R.id.playing_stream_metadata);
    }

    /**
     * Show a notification about the new stream.
     */
    public static void notifyNewStream(String radioName)
    {
        // Remove extra white-spaces from name
        radioName = radioName.trim();

        // Shorten name if it's too long
        if (radioName.length() > Notification.TICKER_MAX_LENGTH)
            radioName = radioName.substring(0, Notification.TICKER_MAX_LENGTH) + "...";

        // Create the Android notification
        Notification.streamNotification = new NotificationCompat.Builder(context)
            .setAutoCancel(false)
            .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
            .setSmallIcon(R.drawable.ic_graphic_eq)
            .setContentTitle(radioName)
            .setContentText(context.getString(R.string.notification_buffering))
            .setTicker(context.getString(R.string.notification_buffering) + " " + radioName)
            .setWhen(0).setUsesChronometer(false).setShowWhen(false);

        Notification.setupLargePlayer();
        Notification.update();

        // Update notification icon with radio logo
        updateNotificationLargeIcon();

        // Update "Now playing" bar with station name
        nowplaying_station.setText(context.getString(R.string.notification_listening) + ": " + radioName);

        // Make the "Now playing" toolbar visible
        nowplaying.setVisibility(View.VISIBLE);
    }

    /**
     * Use a larger notification with buttons.
     */
    public static void setupLargePlayer ()
    {
        // Play/Pause intent when tapping the play/pause button
        // PendingIntent.getBroadcast (Context context, int requestCode, Intent intent, int flags)
        Intent play_intent = new Intent (Player.context, PlayPause.class);
        PendingIntent play_pintent = PendingIntent.getBroadcast (
            Player.context, 0, play_intent, 0);

        // Stop intent when tapping the stop button
        Intent stop_intent = new Intent (Player.context, Stop.class);
        PendingIntent stop_pintent = PendingIntent.getBroadcast (
            Player.context, 0, stop_intent, 0);

        // Intent when tapping the notification (open Main Activity)
        // The .set()/.add() lines below should allow to reopen the
        // existing activity instead of creating a new Main Activity.
        // It works, even though I don't fully understand how.
        Intent mainactivity_intent =
            new Intent (Player.context, MainActivity.class)
                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                .setAction(Intent.ACTION_MAIN)
                .addCategory(Intent.CATEGORY_LAUNCHER);
        PendingIntent mainactivity_pintent = PendingIntent.getActivity (
            Player.context, 0, mainactivity_intent, 0);

        Notification.streamNotification
            // Open app Main Activity on tap
            .setContentIntent(mainactivity_pintent)
            // Add intent when deleting notification
            .setDeleteIntent(stop_pintent)
            // Set fixed (unremovable) notification
            .setOngoing (true);

        // Add buttons
        /*
        if (player.isPlaying())
            Notification.streamNotification
                .addAction (
                    R.drawable.ic_pause,
                    context.getString (R.string.stream_pause),
                    play_pintent)
                .addAction (
                    R.drawable.ic_stop,
                    context.getString (R.string.stream_stop),
                    stop_pintent);
        else
            Notification.streamNotification
                .addAction (
                    R.drawable.ic_play,
                    context.getString (R.string.stream_play),
                    play_pintent)
                .addAction (
                    R.drawable.ic_stop,
                    context.getString (R.string.stream_stop),
                    stop_pintent);
        */
        Notification.streamNotification
            .addAction (
                R.drawable.ic_play,
                context.getString (R.string.stream_play),
                play_pintent)
            .addAction (
                R.drawable.ic_stop,
                context.getString (R.string.stream_stop),
                stop_pintent);
    }

    /**
     * Change notification parameters and update the notification.
     *
     * @param content
     * @param ticker
     * @param largeIcon
     */
    protected static void
    updateNotification (String content, String ticker, Bitmap largeIcon)
    {
        if (Notification.streamNotification == null)
            return;

        // Content is changed to update song info
        if (content != null)
            Notification.streamNotification.setContentText(content);

        // Show a new ticker
        if (ticker != null)
        {
            // Remove leading/trailing spaces
            ticker = ticker.trim();

            // Cut ticker message if it's too long
            if (ticker.length() > Notification.TICKER_MAX_LENGTH)
                ticker = ticker.substring(0, Notification.TICKER_MAX_LENGTH) + "...";

            Notification.streamNotification.setTicker(ticker);
        }

        // Update large icon in notification
        if (largeIcon != null)
            Notification.streamNotification.setLargeIcon(largeIcon);

        Notification.update ();
    }

    /**
     * Send a new async HTTP request to fetch radio image, and then
     * upload the notification with the new logo.
     */
    protected static void updateNotificationLargeIcon()
    {
        RequestQueue queue = Volley.newRequestQueue(context);
        ImageLoader imageLoader = new ImageLoader(queue, new ImageLoader.ImageCache() {
            @Override
            public Bitmap getBitmap(String url) {
                return null;
            }

            @Override
            public void putBitmap(String url, Bitmap bitmap) {

            }
        });

        imageLoader.get(Player.radio.get("logo"), new ImageLoader.ImageListener() {
            @Override
            public void onResponse(ImageLoader.ImageContainer response, boolean isImmediate) {
                Notification.updateNotification(null, null, response.getBitmap());
            }

            @Override
            public void onErrorResponse(VolleyError error) {

            }
        });
    }

    /**
     * Update the notification containing the player.
     * Called after Player.streamNotification has changed and we're
     * ready to submit the new changes.
     */
    protected static void update ()
    {
        // Gets an instance of the NotificationManager service
        NotificationManager mNotifyMgr =
            (NotificationManager) Player.context.getSystemService(
                Player.context.NOTIFICATION_SERVICE);

        // Builds the notification and issues it.
        // Because the ID remains unchanged, the existing notification is updated
        mNotifyMgr.notify (
            Notification.NOTIFICATION_ID,
            Notification.streamNotification.build());
    }

    /**
     * Update the player notification with new metadata about the
     * song that is currently being played.
     */
    protected static void updateStreamMetadata (String metadata)
    {
        if (metadata == null)
            metadata = "";

        if (metadata.length() == 0)
        {
            Notification.updateNotification("", null, null);

            // Change text in the "Now playing" bar
            nowplaying_steam_metadata.setText("");
        } else {
            Notification.updateNotification(
                metadata,
                context.getString(R.string.notification_listening) + metadata,
                null);

            // Change text in the "Now playing" bar
            nowplaying_steam_metadata.setText(metadata);
        }
    }

    // Called from VLC event changed to "playing"
    public static void setPlaying() {
        if (Notification.streamNotification.mActions != null &&
            !Notification.streamNotification.mActions.isEmpty ())
        {
            Notification.streamNotification.mActions.get (0).title =
                context.getString (R.string.stream_pause);

            Notification.streamNotification.mActions.get (0).icon =
                R.drawable.ic_pause;
        }

        // Add a timer to the notification
        Notification.streamNotification
            .setWhen (System.currentTimeMillis ())
            .setUsesChronometer (true)
            .setShowWhen (true);

        Notification.update ();
    }

    // Called from VLC event changed to "stopped"
    public static void setStopped() {
        if (Notification.streamNotification.mActions != null &&
            !Notification.streamNotification.mActions.isEmpty ())
        {
            Notification.streamNotification.mActions.get (0).title =
                context.getString(R.string.stream_play);

            Notification.streamNotification.mActions.get (0).icon =
                R.drawable.ic_play;
        }

        // Remove timer to the notification
        Notification.streamNotification
            .setWhen (0)
            .setUsesChronometer (false)
            .setShowWhen (false);

        Notification.update();
    }

    public static void setPaused() {
        Notification.updateNotification(context.getString(R.string.stream_paused), null, null);
        Notification.nowplaying_steam_metadata.setText("(" + context.getString(R.string.stream_paused) + ")");
    }

    public static void removeAll()
    {
        // Remove the (sticky) notification
        NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

        // Notification ID set when notification was created
        // notificationManager.cancel(Player.NOTIFICATION_ID);
        notificationManager.cancelAll();

        // Hide "Now playing" toolbar
        nowplaying.setVisibility(View.GONE);
    }
}