/*
 * Copyright (c) 2016, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.car.media.localmediaplayer;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.AudioManager;
import android.media.AudioManager.OnAudioFocusChangeListener;
import android.media.MediaDescription;
import android.media.MediaMetadata;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.session.MediaSession;
import android.media.session.MediaSession.QueueItem;
import android.media.session.PlaybackState;
import android.media.session.PlaybackState.CustomAction;
import android.os.Bundle;
import android.util.Log;

import com.android.car.media.localmediaplayer.nano.Proto.Playlist;
import com.android.car.media.localmediaplayer.nano.Proto.Song;

// Proto should be available in AOSP.
import com.google.protobuf.nano.MessageNano;
import com.google.protobuf.nano.InvalidProtocolBufferNanoException;

import java.io.IOException;
import java.io.File;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Collections;
import java.util.List;

/**
 * TODO: Consider doing all content provider accesses and player operations asynchronously.
 */
public class Player extends MediaSession.Callback {
    private static final String TAG = "LMPlayer";
    private static final String SHARED_PREFS_NAME = "com.android.car.media.localmediaplayer.prefs";
    private static final String CURRENT_PLAYLIST_KEY = "__CURRENT_PLAYLIST_KEY__";
    private static final int NOTIFICATION_ID = 42;
    private static final int REQUEST_CODE = 94043;

    private static final float PLAYBACK_SPEED = 1.0f;
    private static final float PLAYBACK_SPEED_STOPPED = 1.0f;
    private static final long PLAYBACK_POSITION_STOPPED = 0;

    // Note: Queues loop around so next/previous are always available.
    private static final long PLAYING_ACTIONS = PlaybackState.ACTION_PAUSE
            | PlaybackState.ACTION_PLAY_FROM_MEDIA_ID | PlaybackState.ACTION_SKIP_TO_NEXT
            | PlaybackState.ACTION_SKIP_TO_PREVIOUS | PlaybackState.ACTION_SKIP_TO_QUEUE_ITEM;

    private static final long PAUSED_ACTIONS = PlaybackState.ACTION_PLAY
            | PlaybackState.ACTION_PLAY_FROM_MEDIA_ID | PlaybackState.ACTION_SKIP_TO_NEXT
            | PlaybackState.ACTION_SKIP_TO_PREVIOUS;

    private static final long STOPPED_ACTIONS = PlaybackState.ACTION_PLAY
            | PlaybackState.ACTION_PLAY_FROM_MEDIA_ID | PlaybackState.ACTION_SKIP_TO_NEXT
            | PlaybackState.ACTION_SKIP_TO_PREVIOUS;

    private static final String SHUFFLE = "android.car.media.localmediaplayer.shuffle";

    private final Context mContext;
    private final MediaSession mSession;
    private final AudioManager mAudioManager;
    private final PlaybackState mErrorState;
    private final DataModel mDataModel;
    private final CustomAction mShuffle;

    private List<QueueItem> mQueue;
    private int mCurrentQueueIdx = 0;
    private final SharedPreferences mSharedPrefs;

    private NotificationManager mNotificationManager;
    private Notification.Builder mPlayingNotificationBuilder;
    private Notification.Builder mPausedNotificationBuilder;

    // TODO: Use multiple media players for gapless playback.
    private final MediaPlayer mMediaPlayer;

    public Player(Context context, MediaSession session, DataModel dataModel) {
        mContext = context;
        mDataModel = dataModel;
        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        mSession = session;
        mSharedPrefs = context.getSharedPreferences(SHARED_PREFS_NAME, Context.MODE_PRIVATE);

        mShuffle = new CustomAction.Builder(SHUFFLE, context.getString(R.string.shuffle),
                R.drawable.shuffle).build();

        mMediaPlayer = new MediaPlayer();
        mMediaPlayer.reset();
        mMediaPlayer.setOnCompletionListener(mOnCompletionListener);
        mErrorState = new PlaybackState.Builder()
                .setState(PlaybackState.STATE_ERROR, 0, 0)
                .setErrorMessage(context.getString(R.string.playback_error))
                .build();

        mNotificationManager =
                (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

        // There are 2 forms of the media notification, when playing it needs to show the controls
        // to pause & skip whereas when paused it needs to show controls to play & skip. Setup
        // pre-populated builders for both of these up front.
        Notification.Action prevAction = makeNotificationAction(
                LocalMediaBrowserService.ACTION_PREV, R.drawable.ic_prev, R.string.prev);
        Notification.Action nextAction = makeNotificationAction(
                LocalMediaBrowserService.ACTION_NEXT, R.drawable.ic_next, R.string.next);
        Notification.Action playAction = makeNotificationAction(
                LocalMediaBrowserService.ACTION_PLAY, R.drawable.ic_play, R.string.play);
        Notification.Action pauseAction = makeNotificationAction(
                LocalMediaBrowserService.ACTION_PAUSE, R.drawable.ic_pause, R.string.pause);

        // While playing, you need prev, pause, next.
        mPlayingNotificationBuilder = new Notification.Builder(context)
                .setVisibility(Notification.VISIBILITY_PUBLIC)
                .setSmallIcon(R.drawable.ic_sd_storage_black)
                .addAction(prevAction)
                .addAction(pauseAction)
                .addAction(nextAction);

        // While paused, you need prev, play, next.
        mPausedNotificationBuilder = new Notification.Builder(context)
                .setVisibility(Notification.VISIBILITY_PUBLIC)
                .setSmallIcon(R.drawable.ic_sd_storage_black)
                .addAction(prevAction)
                .addAction(playAction)
                .addAction(nextAction);
    }

    private Notification.Action makeNotificationAction(String action, int iconId, int stringId) {
        PendingIntent intent = PendingIntent.getBroadcast(mContext, REQUEST_CODE,
                new Intent(action), PendingIntent.FLAG_UPDATE_CURRENT);
        Notification.Action notificationAction = new Notification.Action.Builder(iconId,
                mContext.getString(stringId), intent)
                .build();
        return notificationAction;
    }

    private boolean requestAudioFocus(Runnable onSuccess) {
        int result = mAudioManager.requestAudioFocus(mAudioFocusListener, AudioManager.STREAM_MUSIC,
                AudioManager.AUDIOFOCUS_GAIN);
        if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
            onSuccess.run();
            return true;
        }
        Log.e(TAG, "Failed to acquire audio focus");
        return false;
    }

    @Override
    public void onPlay() {
        super.onPlay();
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "onPlay");
        }
        // Check permissions every time we try to play
        if (!Utils.hasRequiredPermissions(mContext)) {
            Utils.startPermissionRequest(mContext);
        } else {
            requestAudioFocus(() -> resumePlayback());
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "onPause");
        }
        pausePlayback();
        mAudioManager.abandonAudioFocus(mAudioFocusListener);
    }

    public void destroy() {
        stopPlayback();
        mNotificationManager.cancelAll();
        mAudioManager.abandonAudioFocus(mAudioFocusListener);
        mMediaPlayer.release();
    }

    public void saveState() {
        if (mQueue == null || mQueue.isEmpty()) {
            return;
        }

        Playlist playlist = new Playlist();
        playlist.songs = new Song[mQueue.size()];

        int idx = 0;
        for (QueueItem item : mQueue) {
            Song song = new Song();
            song.queueId = item.getQueueId();
            MediaDescription description = item.getDescription();
            song.mediaId = description.getMediaId();
            song.title = description.getTitle().toString();
            song.subtitle = description.getSubtitle().toString();
            song.path = description.getExtras().getString(DataModel.PATH_KEY);

            playlist.songs[idx] = song;
            idx++;
        }
        playlist.currentQueueId = mQueue.get(mCurrentQueueIdx).getQueueId();
        playlist.currentSongPosition = mMediaPlayer.getCurrentPosition();
        playlist.name = CURRENT_PLAYLIST_KEY;

        // Go to Base64 to ensure that we can actually store the string in a sharedpref. This is
        // slightly wasteful because of the fact that base64 expands the size a bit but it's a
        // lot less riskier than abusing the java string to directly store bytes coming out of
        // proto encoding.
        String serialized = Base64.getEncoder().encodeToString(MessageNano.toByteArray(playlist));
        SharedPreferences.Editor editor = mSharedPrefs.edit();
        editor.putString(CURRENT_PLAYLIST_KEY, serialized);
        editor.commit();
    }

    private boolean maybeRebuildQueue(Playlist playlist) {
        List<QueueItem> queue = new ArrayList<>();
        int foundIdx = 0;
        // You need to check if the playlist actually is still valid because the user could have
        // deleted files or taken out the sd card between runs so we might as well check this ahead
        // of time before we load up the playlist.
        for (Song song : playlist.songs) {
            File tmp = new File(song.path);
            if (!tmp.exists()) {
                continue;
            }

            if (playlist.currentQueueId == song.queueId) {
                foundIdx = queue.size();
            }

            Bundle bundle = new Bundle();
            bundle.putString(DataModel.PATH_KEY, song.path);
            MediaDescription description = new MediaDescription.Builder()
                    .setMediaId(song.mediaId)
                    .setTitle(song.title)
                    .setSubtitle(song.subtitle)
                    .setExtras(bundle)
                    .build();
            queue.add(new QueueItem(description, song.queueId));
        }

        if (queue.isEmpty()) {
            return false;
        }

        mQueue = queue;
        mCurrentQueueIdx = foundIdx;  // Resumes from beginning if last playing song was not found.

        return true;
    }

    public boolean maybeRestoreState() {
        String serialized = mSharedPrefs.getString(CURRENT_PLAYLIST_KEY, null);
        if (serialized == null) {
            return false;
        }

        try {
            Playlist playlist = Playlist.parseFrom(Base64.getDecoder().decode(serialized));
            if (!maybeRebuildQueue(playlist)) {
                return false;
            }
            updateSessionQueueState();

            requestAudioFocus(() -> {
                try {
                    playCurrentQueueIndex();
                    mMediaPlayer.seekTo(playlist.currentSongPosition);
                    updatePlaybackStatePlaying();
                } catch (IOException e) {
                    Log.e(TAG, "Restored queue, but couldn't resume playback.");
                }
            });
        } catch (IllegalArgumentException | InvalidProtocolBufferNanoException e) {
            // Couldn't restore the playlist. Not the end of the world.
            return false;
        }

        return true;
    }

    private void updateSessionQueueState() {
        mSession.setQueueTitle(mContext.getString(R.string.playlist));
        mSession.setQueue(mQueue);
    }

    private void startPlayback(String key) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "startPlayback()");
        }

        List<QueueItem> queue = mDataModel.getQueue();
        int idx = 0;
        int foundIdx = -1;
        for (QueueItem item : queue) {
            if (item.getDescription().getMediaId().equals(key)) {
                foundIdx = idx;
                break;
            }
            idx++;
        }

        if (foundIdx == -1) {
            mSession.setPlaybackState(mErrorState);
            return;
        }

        mQueue = new ArrayList<>(queue);
        mCurrentQueueIdx = foundIdx;
        QueueItem current = mQueue.get(mCurrentQueueIdx);
        String path = current.getDescription().getExtras().getString(DataModel.PATH_KEY);
        MediaMetadata metadata = mDataModel.getMetadata(current.getDescription().getMediaId());
        updateSessionQueueState();

        try {
            play(path, metadata);
        } catch (IOException e) {
            Log.e(TAG, "Playback failed.", e);
            mSession.setPlaybackState(mErrorState);
        }
    }

    private void resumePlayback() {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "resumePlayback()");
        }

        updatePlaybackStatePlaying();

        if (!mMediaPlayer.isPlaying()) {
            mMediaPlayer.start();
        }
    }

    private void postMediaNotification(Notification.Builder builder) {
        if (mQueue == null) {
            return;
        }

        MediaDescription current = mQueue.get(mCurrentQueueIdx).getDescription();
        Notification notification = builder
                .setStyle(new Notification.MediaStyle().setMediaSession(mSession.getSessionToken()))
                .setContentTitle(current.getTitle())
                .setContentText(current.getSubtitle())
                .setShowWhen(false)
                .build();
        notification.flags |= Notification.FLAG_NO_CLEAR;
        mNotificationManager.notify(NOTIFICATION_ID, notification);
    }

    private void updatePlaybackStatePlaying() {
        if (!mSession.isActive()) {
            mSession.setActive(true);
        }

        // Update the state in the media session.
        PlaybackState state = new PlaybackState.Builder()
                .setState(PlaybackState.STATE_PLAYING,
                        mMediaPlayer.getCurrentPosition(), PLAYBACK_SPEED)
                .setActions(PLAYING_ACTIONS)
                .addCustomAction(mShuffle)
                .setActiveQueueItemId(mQueue.get(mCurrentQueueIdx).getQueueId())
                .build();
        mSession.setPlaybackState(state);

        // Update the media styled notification.
        postMediaNotification(mPlayingNotificationBuilder);
    }

    private void pausePlayback() {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "pausePlayback()");
        }

        long currentPosition = 0;
        if (mMediaPlayer.isPlaying()) {
            currentPosition = mMediaPlayer.getCurrentPosition();
            mMediaPlayer.pause();
        }

        PlaybackState state = new PlaybackState.Builder()
                .setState(PlaybackState.STATE_PAUSED, currentPosition, PLAYBACK_SPEED_STOPPED)
                .setActions(PAUSED_ACTIONS)
                .addCustomAction(mShuffle)
                .build();
        mSession.setPlaybackState(state);

        // Update the media styled notification.
        postMediaNotification(mPausedNotificationBuilder);
    }

    private void stopPlayback() {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "stopPlayback()");
        }

        if (mMediaPlayer.isPlaying()) {
            mMediaPlayer.stop();
        }

        PlaybackState state = new PlaybackState.Builder()
                .setState(PlaybackState.STATE_STOPPED, PLAYBACK_POSITION_STOPPED,
                        PLAYBACK_SPEED_STOPPED)
                .setActions(STOPPED_ACTIONS)
                .build();
        mSession.setPlaybackState(state);
    }

    private void advance() throws IOException {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "advance()");
        }
        // Go to the next song if one exists. Note that if you were to support gapless
        // playback, you would have to change this code such that you had a currently
        // playing and a loading MediaPlayer and juggled between them while also calling
        // setNextMediaPlayer.

        if (mQueue != null && !mQueue.isEmpty()) {
            // Keep looping around when we run off the end of our current queue.
            mCurrentQueueIdx = (mCurrentQueueIdx + 1) % mQueue.size();
            playCurrentQueueIndex();
        } else {
            stopPlayback();
        }
    }

    private void retreat() throws IOException {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "retreat()");
        }
        // Go to the next song if one exists. Note that if you were to support gapless
        // playback, you would have to change this code such that you had a currently
        // playing and a loading MediaPlayer and juggled between them while also calling
        // setNextMediaPlayer.
        if (mQueue != null) {
            // Keep looping around when we run off the end of our current queue.
            mCurrentQueueIdx--;
            if (mCurrentQueueIdx < 0) {
                mCurrentQueueIdx = mQueue.size() - 1;
            }
            playCurrentQueueIndex();
        } else {
            stopPlayback();
        }
    }

    private void playCurrentQueueIndex() throws IOException {
        MediaDescription next = mQueue.get(mCurrentQueueIdx).getDescription();
        String path = next.getExtras().getString(DataModel.PATH_KEY);
        MediaMetadata metadata = mDataModel.getMetadata(next.getMediaId());

        play(path, metadata);
    }

    private void play(String path, MediaMetadata metadata) throws IOException {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "play path=" + path + " metadata=" + metadata);
        }

        mMediaPlayer.reset();
        mMediaPlayer.setDataSource(path);
        mMediaPlayer.prepare();

        if (metadata != null) {
            mSession.setMetadata(metadata);
        }
        boolean wasGrantedAudio = requestAudioFocus(() -> {
            mMediaPlayer.start();
            updatePlaybackStatePlaying();
        });
        if (!wasGrantedAudio) {
            // player.pause() isn't needed since it should not actually be playing, the
            // other steps like, updating the notification and play state are needed, thus we
            // call the pause method.
            pausePlayback();
        }
    }

    private void safeAdvance() {
        try {
            advance();
        } catch (IOException e) {
            Log.e(TAG, "Failed to advance.", e);
            mSession.setPlaybackState(mErrorState);
        }
    }

    private void safeRetreat() {
        try {
            retreat();
        } catch (IOException e) {
            Log.e(TAG, "Failed to advance.", e);
            mSession.setPlaybackState(mErrorState);
        }
    }

    /**
     * This is a naive implementation of shuffle, previously played songs may repeat after the
     * shuffle operation. Only call this from the main thread.
     */
    private void shuffle() {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "Shuffling");
        }

        // rebuild the the queue in a shuffled form.
        if (mQueue != null && mQueue.size() > 2) {
            QueueItem current = mQueue.remove(mCurrentQueueIdx);
            Collections.shuffle(mQueue);
            mQueue.add(0, current);
            // A QueueItem contains a queue id that's used as the key for when the user selects
            // the current play list. This means the QueueItems must be rebuilt to have their new
            // id's set.
            for (int i = 0; i < mQueue.size(); i++) {
                mQueue.set(i, new QueueItem(mQueue.get(i).getDescription(), i));
            }
            mCurrentQueueIdx = 0;
            updateSessionQueueState();
        }
    }

    @Override
    public void onPlayFromMediaId(String mediaId, Bundle extras) {
        super.onPlayFromMediaId(mediaId, extras);
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "onPlayFromMediaId mediaId" + mediaId + " extras=" + extras);
        }

        requestAudioFocus(() -> startPlayback(mediaId));
    }

    @Override
    public void onSkipToNext() {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "onSkipToNext()");
        }
        safeAdvance();
    }

    @Override
    public void onSkipToPrevious() {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "onSkipToPrevious()");
        }
        safeRetreat();
    }

    @Override
    public void onSkipToQueueItem(long id) {
        try {
            mCurrentQueueIdx = (int) id;
            playCurrentQueueIndex();
        } catch (IOException e) {
            Log.e(TAG, "Failed to play.", e);
            mSession.setPlaybackState(mErrorState);
        }
    }

    @Override
    public void onCustomAction(String action, Bundle extras) {
        switch (action) {
            case SHUFFLE:
                shuffle();
                break;
            default:
                Log.e(TAG, "Unhandled custom action: " + action);
        }
    }

    private OnAudioFocusChangeListener mAudioFocusListener = new OnAudioFocusChangeListener() {
        @Override
        public void onAudioFocusChange(int focus) {
            switch (focus) {
                case AudioManager.AUDIOFOCUS_GAIN:
                    resumePlayback();
                    break;
                case AudioManager.AUDIOFOCUS_LOSS:
                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
                    pausePlayback();
                    break;
                default:
                    Log.e(TAG, "Unhandled audio focus type: " + focus);
            }
        }
    };

    private OnCompletionListener mOnCompletionListener = new OnCompletionListener() {
        @Override
        public void onCompletion(MediaPlayer mediaPlayer) {
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "onCompletion()");
            }
            safeAdvance();
        }
    };
}
