/*
 * Created by Oliver Bell on 15/01/2017
 * Copyright (c) 2017. by Oliver bell <[email protected]>
 *
 * Last modified 14/06/17 23:15
 */

package com.freshollie.monkeyboard.keystoneradio.playback;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import java.text.DecimalFormat;

import android.os.Build;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.res.ResourcesCompat;
import android.support.v4.media.MediaMetadataCompat;
import android.support.v4.media.session.MediaControllerCompat;
import android.support.v4.media.session.PlaybackStateCompat;
import android.support.v4.app.NotificationCompat;
import android.support.v4.media.app.NotificationCompat.MediaStyle;
import android.util.FloatMath;
import android.util.Log;

import com.freshollie.monkeyboard.keystoneradio.radio.RadioDevice;
import com.freshollie.monkeyboard.keystoneradio.ui.PlayerActivity;
import com.freshollie.monkeyboard.keystoneradio.R;

/**
 * Handles the player service notification, will update using the players metadata when
 * requested
 */
public class RadioPlayerNotification extends MediaControllerCompat.Callback {
    private RadioPlayerService playerService;
    private NotificationCompat.Builder mediaNotificationBuilder;
    private NotificationManager notificationManager;

    private boolean wasPlaying = false;
    private int lastFrequency;

    private int NOTIFICATION_ID = 1;

    private static final String CHANNEL_ID = "RADIO";

    public RadioPlayerNotification(RadioPlayerService service) {
        playerService = service;
        notificationManager = (NotificationManager)
                playerService.getSystemService(Context.NOTIFICATION_SERVICE);

        // Create a notification channel for
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            CharSequence name = "Media playback";
            String description = "Media playback controls";

            NotificationChannel channel = new NotificationChannel(
                    CHANNEL_ID,
                    name,
                    NotificationManager.IMPORTANCE_LOW
            );
            channel.setDescription(description);
            channel.setShowBadge(false);
            channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);

            notificationManager.createNotificationChannel(channel);
        }

        Log.d("RadioPlayerNotification", "Starting foreground");
        playerService.getMediaSession().setActive(true);
        playerService.getMediaController().registerCallback(this);

        update();
    }

    private int getDominantColor(Bitmap bitmap) {
        if (null == bitmap) return Color.TRANSPARENT;

        int redBucket = 0;
        int greenBucket = 0;
        int blueBucket = 0;
        int alphaBucket = 0;

        boolean hasAlpha = bitmap.hasAlpha();
        int pixelCount = bitmap.getWidth() * bitmap.getHeight();
        int[] pixels = new int[pixelCount];
        bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());

        for (int y = 0, h = bitmap.getHeight(); y < h; y++)
        {
            for (int x = 0, w = bitmap.getWidth(); x < w; x++)
            {
                int color = pixels[x + y * w]; // x + y * width
                redBucket += (color >> 16) & 0xFF; // Color.red
                greenBucket += (color >> 8) & 0xFF; // Color.greed
                blueBucket += (color & 0xFF); // Color.blue
                if (hasAlpha) alphaBucket += (color >>> 24); // Color.alpha
            }
        }

        return Color.argb(
                (hasAlpha) ? (alphaBucket / pixelCount) : 255,
                redBucket / pixelCount,
                greenBucket / pixelCount,
                blueBucket / pixelCount);
    }

    private Bitmap letterboxImage(Bitmap srcBmp) {
        int dim = Math.max(srcBmp.getWidth(), srcBmp.getHeight());
        Bitmap dstBmp = Bitmap.createBitmap(dim, dim, Bitmap.Config.ARGB_8888);

        Canvas canvas = new Canvas(dstBmp);
        canvas.drawColor(getDominantColor(srcBmp));
        canvas.drawBitmap(srcBmp, (dim - srcBmp.getWidth()) / 2, (dim - srcBmp.getHeight()) / 2, null);

        return dstBmp;
    }

    private Notification buildNotification() {
        int playIcon;
        String playAction;
        String playDescription;
        NotificationCompat.Builder builder = new NotificationCompat.Builder(playerService, CHANNEL_ID);

        // Used for setting a pause of play icon and action depending on the current play state
        if (playerService.getPlaybackState() == PlaybackStateCompat.STATE_PLAYING) {
            playIcon = R.drawable.ic_notification_pause;
            playAction = RadioPlayerService.ACTION_PAUSE;
            playDescription = "pause";
            builder.setOngoing(true);
        } else {
            playIcon = R.drawable.ic_notification_play;
            playAction = RadioPlayerService.ACTION_PLAY;
            playDescription = "play";
        }

        if (playerService.getRadioMode() == RadioDevice.Values.STREAM_MODE_FM) {

            String trackName = playerService.getMetadata()
                    .getString(MediaMetadataCompat.METADATA_KEY_TITLE);

            if (trackName == null || trackName.isEmpty()) {
                trackName = new DecimalFormat("#.0").format(
                                    playerService.getMetadata().getLong(
                                            MediaMetadataCompat.METADATA_KEY_TRACK_NUMBER
                                    ) / 1000.0
                );
            }

            return builder.setShowWhen(false)
                    .setLargeIcon(
                            ((BitmapDrawable) ResourcesCompat.getDrawableForDensity(
                                    playerService.getResources(),
                                    R.mipmap.ic_launcher,
                                    480,
                                    null
                            )).getBitmap()
                    )
                    .setSmallIcon(R.drawable.ic_notification_radio)
                    .setColor(ContextCompat.getColor(playerService, R.color.colorPrimaryDark))
                    .setContentIntent(
                            PendingIntent.getActivity(
                                    playerService,
                                    0,
                                    new Intent(playerService, PlayerActivity.class),
                                    PendingIntent.FLAG_UPDATE_CURRENT
                            )
                    )
                    .setStyle(
                            new MediaStyle()
                                    .setMediaSession(
                                            playerService.getMediaSession()
                                                    .getSessionToken()
                                    )
                                    .setShowCancelButton(true)
                                    .setShowActionsInCompactView(0, 2, 4)
                                    .setCancelButtonIntent(
                                            getPendingIntentForAction(
                                                    RadioPlayerService.ACTION_STOP
                                            )
                                    )
                    )
                    .setContentTitle(trackName)
                    .setContentInfo(
                            playerService.getMetadata().getString(
                                    MediaMetadataCompat.METADATA_KEY_GENRE
                            )
                    )
                    .setContentText(
                            playerService.getMetadata().getString(
                                    MediaMetadataCompat.METADATA_KEY_DISPLAY_DESCRIPTION
                            )
                    )
                    .addAction(
                            R.drawable.ic_notification_skip_prev,
                            "prev",
                            getPendingIntentForAction(RadioPlayerService.ACTION_PREVIOUS)
                    )
                    .addAction(
                            R.drawable.ic_notification_rewind,
                            "search_backwards",
                            getPendingIntentForAction(RadioPlayerService.ACTION_SEARCH_BACKWARDS)
                    )
                    .addAction(
                            playIcon,
                            playDescription,
                            getPendingIntentForAction(playAction)
                    )
                    .addAction(
                            R.drawable.ic_notification_fast_forward,
                            "search_forwards",
                            getPendingIntentForAction(RadioPlayerService.ACTION_SEARCH_FORWARDS)
                    )
                    .addAction(
                            R.drawable.ic_notification_skip_next,
                            "next",
                            getPendingIntentForAction(RadioPlayerService.ACTION_NEXT)
                    )
                    .setDeleteIntent(
                            getPendingIntentForAction(
                                    RadioPlayerService.ACTION_STOP
                            )
                    )
                    .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
                    .build();
        } else {
            Bitmap notificationImage =
                    playerService
                    .getMetadata()
                    .getBitmap(MediaMetadataCompat.METADATA_KEY_ART);

            if (notificationImage == null) {
                notificationImage = ((BitmapDrawable) ResourcesCompat.getDrawableForDensity(
                        playerService.getResources(),
                        R.mipmap.ic_launcher,
                        480,
                        null
                )).getBitmap();
            } else {
                // Letterbox the image inside a square so that it displays probably in the
                // notification
                notificationImage = letterboxImage(notificationImage);
            }

            return builder.setShowWhen(false)
                    .setLargeIcon(notificationImage)
                    .setSmallIcon(R.drawable.ic_notification_radio)
                    .setColor(ContextCompat.getColor(playerService, R.color.colorPrimaryDark))
                    .setContentIntent(
                            PendingIntent.getActivity(
                                    playerService,
                                    0,
                                    new Intent(playerService, PlayerActivity.class),
                                    PendingIntent.FLAG_UPDATE_CURRENT
                            )
                    )
                    .setStyle(
                            new MediaStyle()
                                    .setMediaSession(
                                            playerService.getMediaSession()
                                                    .getSessionToken()
                                    )
                                    .setShowCancelButton(true)
                                    .setShowActionsInCompactView(0, 1, 2)
                                    .setCancelButtonIntent(
                                            getPendingIntentForAction(
                                                    RadioPlayerService.ACTION_STOP
                                            )
                                    )
                    )
                    .setContentTitle(playerService.getMetadata()
                            .getString(MediaMetadataCompat.METADATA_KEY_TITLE)
                    )
                    .setContentInfo(
                            playerService.getMetadata().getString(
                                    MediaMetadataCompat.METADATA_KEY_GENRE
                            )
                    )
                    .setContentText(
                            playerService.getMetadata().getString(
                                MediaMetadataCompat.METADATA_KEY_DISPLAY_DESCRIPTION
                        )
                    )
                    .addAction(
                            R.drawable.ic_notification_skip_prev,
                            "prev",
                            getPendingIntentForAction(RadioPlayerService.ACTION_PREVIOUS)
                    )
                    .addAction(
                            playIcon,
                            playDescription,
                            getPendingIntentForAction(playAction)
                    )
                    .addAction(
                            R.drawable.ic_notification_skip_next,
                            "next",
                            getPendingIntentForAction(RadioPlayerService.ACTION_NEXT)
                    )
                    .setDeleteIntent(
                            getPendingIntentForAction(
                                    RadioPlayerService.ACTION_STOP
                            )
                    )
                    .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
                    .build();
        }
    }

    private PendingIntent getPendingIntentForAction(String action) {
        return PendingIntent.getService(
                playerService,
                0,
                new Intent(playerService, RadioPlayerService.class)
                        .setAction(action),
                PendingIntent.FLAG_UPDATE_CURRENT
        );
    }

    private void update() {
        if (playerService.getPlaybackState() == PlaybackStateCompat.STATE_PLAYING) {
            playerService.startForeground(
                    NOTIFICATION_ID,
                    buildNotification()
            );
        } else {
            playerService.stopForeground(false);
            notificationManager.notify(
                    NOTIFICATION_ID,
                    buildNotification()
            );
        }
    }

    public void cancel() {
        playerService.getMediaSession().setActive(false);
        notificationManager.cancel(NOTIFICATION_ID);
        playerService.stopForeground(true);
        playerService.getMediaController().unregisterCallback(this);
    }

    @Override
    public void onMetadataChanged(MediaMetadataCompat metadata) {
        update();
    }

    @Override
    public void onPlaybackStateChanged(PlaybackStateCompat state) {
        update();
    }
}