/*
 * 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");
        }
        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 = 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())
                .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();
        mMediaPlayer.start();

        if (metadata != null) {
            mSession.setMetadata(metadata);
        }
        updatePlaybackStatePlaying();
    }

    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");
        }

        if (mQueue != null) {
            QueueItem current = mQueue.remove(mCurrentQueueIdx);
            Collections.shuffle(mQueue);
            mQueue.add(0, current);
            mCurrentQueueIdx = 0;
            updateSessionQueueState();
            updatePlaybackStatePlaying();
        }
    }

    @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) {
        int idx = (int) id;
        MediaSession.QueueItem item = mQueue.get(idx);
        MediaDescription description = item.getDescription();

        String path = description.getExtras().getString(DataModel.PATH_KEY);
        MediaMetadata metadata = mDataModel.getMetadata(description.getMediaId());

        try {
            play(path, metadata);
            mCurrentQueueIdx = idx;
        } 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();
        }
    };
}
