/*
 * Copyright (C) 2013 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.example.android.supportv7.media;

import android.app.PendingIntent;
import android.net.Uri;
import android.support.v7.media.MediaItemStatus;
import android.support.v7.media.MediaSessionStatus;
import android.util.Log;

import java.util.List;
import java.util.ArrayList;

/**
 * SessionManager manages a media session as a queue. It supports common
 * queuing behaviors such as enqueue/remove of media items, pause/resume/stop,
 * etc.
 *
 * Actual playback of a single media item is abstracted into a Player interface,
 * and is handled outside this class.
 */
public class SessionManager implements Player.Callback {
    private static final String TAG = "SessionManager";
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);

    private String mName;
    private int mSessionId;
    private int mItemId;
    private boolean mPaused;
    private boolean mSessionValid;
    private Player mPlayer;
    private Callback mCallback;
    private List<PlaylistItem> mPlaylist = new ArrayList<PlaylistItem>();

    public SessionManager(String name) {
        mName = name;
    }

    public boolean isPaused() {
        return hasSession() && mPaused;
    }

    public boolean hasSession() {
        return mSessionValid;
    }

    public String getSessionId() {
        return mSessionValid ? Integer.toString(mSessionId) : null;
    }

    public PlaylistItem getCurrentItem() {
        return mPlaylist.isEmpty() ? null : mPlaylist.get(0);
    }

    // Returns the cached playlist (note this is not responsible for updating it)
    public List<PlaylistItem> getPlaylist() {
        return mPlaylist;
    }

    // Updates the playlist asynchronously, calls onPlaylistReady() when finished.
    public void updateStatus() {
        if (DEBUG) {
            log("updateStatus");
        }
        checkPlayer();
        // update the statistics first, so that the stats string is valid when
        // onPlaylistReady() gets called in the end
        mPlayer.updateTrackInfo();

        if (mPlaylist.isEmpty()) {
            // If queue is empty, don't forget to call onPlaylistReady()!
            onPlaylistReady();
        } else if (mPlayer.isQueuingSupported()) {
            // If player supports queuing, get status of each item. Player is
            // responsible to call onPlaylistReady() after last getStatus().
            // (update=1 requires player to callback onPlaylistReady())
            for (int i = 0; i < mPlaylist.size(); i++) {
                PlaylistItem item = mPlaylist.get(i);
                mPlayer.getStatus(item, (i == mPlaylist.size() - 1) /* update */);
            }
        } else {
            // Otherwise, only need to get status for current item. Player is
            // responsible to call onPlaylistReady() when finished.
            mPlayer.getStatus(getCurrentItem(), true /* update */);
        }
    }

    public PlaylistItem add(Uri uri, String mime) {
        return add(uri, mime, null);
    }

    public PlaylistItem add(Uri uri, String mime, PendingIntent receiver) {
        if (DEBUG) {
            log("add: uri=" + uri + ", receiver=" + receiver);
        }
        // create new session if needed
        startSession();
        checkPlayerAndSession();

        // append new item with initial status PLAYBACK_STATE_PENDING
        PlaylistItem item = new PlaylistItem(
                Integer.toString(mSessionId), Integer.toString(mItemId), uri, mime, receiver);
        mPlaylist.add(item);
        mItemId++;

        // if player supports queuing, enqueue the item now
        if (mPlayer.isQueuingSupported()) {
            mPlayer.enqueue(item);
        }
        updatePlaybackState();
        return item;
    }

    public PlaylistItem remove(String iid) {
        if (DEBUG) {
            log("remove: iid=" + iid);
        }
        checkPlayerAndSession();
        return removeItem(iid, MediaItemStatus.PLAYBACK_STATE_CANCELED);
    }

    public PlaylistItem seek(String iid, long pos) {
        if (DEBUG) {
            log("seek: iid=" + iid +", pos=" + pos);
        }
        checkPlayerAndSession();
        // seeking on pending items are not yet supported
        checkItemCurrent(iid);

        PlaylistItem item = getCurrentItem();
        if (pos != item.getPosition()) {
            item.setPosition(pos);
            if (item.getState() == MediaItemStatus.PLAYBACK_STATE_PLAYING
                    || item.getState() == MediaItemStatus.PLAYBACK_STATE_PAUSED) {
                mPlayer.seek(item);
            }
        }
        return item;
    }

    public PlaylistItem getStatus(String iid) {
        checkPlayerAndSession();

        // This should only be called for local player. Remote player is
        // asynchronous, need to use updateStatus() instead.
        if (mPlayer.isRemotePlayback()) {
            throw new IllegalStateException(
                    "getStatus should not be called on remote player!");
        }

        for (PlaylistItem item : mPlaylist) {
            if (item.getItemId().equals(iid)) {
                if (item == getCurrentItem()) {
                    mPlayer.getStatus(item, false);
                }
                return item;
            }
        }
        return null;
    }

    public void pause() {
        if (DEBUG) {
            log("pause");
        }
        if (!mSessionValid) {
            return;
        }
        checkPlayer();
        mPaused = true;
        updatePlaybackState();
    }

    public void resume() {
        if (DEBUG) {
            log("resume");
        }
        if (!mSessionValid) {
            return;
        }
        checkPlayer();
        mPaused = false;
        updatePlaybackState();
    }

    public void stop() {
        if (DEBUG) {
            log("stop");
        }
        if (!mSessionValid) {
            return;
        }
        checkPlayer();
        mPlayer.stop();
        mPlaylist.clear();
        mPaused = false;
        updateStatus();
    }

    public String startSession() {
        if (!mSessionValid) {
            mSessionId++;
            mItemId = 0;
            mPaused = false;
            mSessionValid = true;
            return Integer.toString(mSessionId);
        }
        return null;
    }

    public boolean endSession() {
        if (mSessionValid) {
            mSessionValid = false;
            return true;
        }
        return false;
    }

    MediaSessionStatus getSessionStatus(String sid) {
        int sessionState = (sid != null && sid.equals(mSessionId)) ?
                MediaSessionStatus.SESSION_STATE_ACTIVE :
                    MediaSessionStatus.SESSION_STATE_INVALIDATED;

        return new MediaSessionStatus.Builder(sessionState)
                .setQueuePaused(mPaused)
                .build();
    }

    // Suspend the playback manager. Put the current item back into PENDING
    // state, and remember the current playback position. Called when switching
    // to a different player (route).
    public void suspend(long pos) {
        for (PlaylistItem item : mPlaylist) {
            item.setRemoteItemId(null);
            item.setDuration(0);
        }
        PlaylistItem item = getCurrentItem();
        if (DEBUG) {
            log("suspend: item=" + item + ", pos=" + pos);
        }
        if (item != null) {
            if (item.getState() == MediaItemStatus.PLAYBACK_STATE_PLAYING
                    || item.getState() == MediaItemStatus.PLAYBACK_STATE_PAUSED) {
                item.setState(MediaItemStatus.PLAYBACK_STATE_PENDING);
                item.setPosition(pos);
            }
        }
    }

    // Unsuspend the playback manager. Restart playback on new player (route).
    // This will resume playback of current item. Furthermore, if the new player
    // supports queuing, playlist will be re-established on the remote player.
    public void unsuspend() {
        if (DEBUG) {
            log("unsuspend");
        }
        if (mPlayer.isQueuingSupported()) {
            for (PlaylistItem item : mPlaylist) {
                mPlayer.enqueue(item);
            }
        }
        updatePlaybackState();
    }

    // Player.Callback
    @Override
    public void onError() {
        finishItem(true);
    }

    @Override
    public void onCompletion() {
        finishItem(false);
    }

    @Override
    public void onPlaylistChanged() {
        // Playlist has changed, update the cached playlist
        updateStatus();
    }

    @Override
    public void onPlaylistReady() {
        // Notify activity to update Ui
        if (mCallback != null) {
            mCallback.onStatusChanged();
        }
    }

    private void log(String message) {
        Log.d(TAG, mName + ": " + message);
    }

    private void checkPlayer() {
        if (mPlayer == null) {
            throw new IllegalStateException("Player not set!");
        }
    }

    private void checkSession() {
        if (!mSessionValid) {
            throw new IllegalStateException("Session not set!");
        }
    }

    private void checkPlayerAndSession() {
        checkPlayer();
        checkSession();
    }

    private void checkItemCurrent(String iid) {
        PlaylistItem item = getCurrentItem();
        if (item == null || !item.getItemId().equals(iid)) {
            throw new IllegalArgumentException("Item is not current!");
        }
    }

    private void updatePlaybackState() {
        PlaylistItem item = getCurrentItem();
        if (item != null) {
            if (item.getState() == MediaItemStatus.PLAYBACK_STATE_PENDING) {
                item.setState(mPaused ? MediaItemStatus.PLAYBACK_STATE_PAUSED
                        : MediaItemStatus.PLAYBACK_STATE_PLAYING);
                if (!mPlayer.isQueuingSupported()) {
                    mPlayer.play(item);
                }
            } else if (mPaused && item.getState() == MediaItemStatus.PLAYBACK_STATE_PLAYING) {
                mPlayer.pause();
                item.setState(MediaItemStatus.PLAYBACK_STATE_PAUSED);
            } else if (!mPaused && item.getState() == MediaItemStatus.PLAYBACK_STATE_PAUSED) {
                mPlayer.resume();
                item.setState(MediaItemStatus.PLAYBACK_STATE_PLAYING);
            }
            // notify client that item playback status has changed
            if (mCallback != null) {
                mCallback.onItemChanged(item);
            }
        } else {
            mPlayer.initMediaSession();
        }
        updateStatus();
    }

    private PlaylistItem removeItem(String iid, int state) {
        checkPlayerAndSession();
        List<PlaylistItem> queue =
                new ArrayList<PlaylistItem>(mPlaylist.size());
        PlaylistItem found = null;
        for (PlaylistItem item : mPlaylist) {
            if (iid.equals(item.getItemId())) {
                if (mPlayer.isQueuingSupported()) {
                    mPlayer.remove(item.getRemoteItemId());
                } else if (item.getState() == MediaItemStatus.PLAYBACK_STATE_PLAYING
                        || item.getState() == MediaItemStatus.PLAYBACK_STATE_PAUSED){
                    mPlayer.stop();
                }
                item.setState(state);
                found = item;
                // notify client that item is now removed
                if (mCallback != null) {
                    mCallback.onItemChanged(found);
                }
            } else {
                queue.add(item);
            }
        }
        if (found != null) {
            mPlaylist = queue;
            updatePlaybackState();
        } else {
            log("item not found");
        }
        return found;
    }

    private void finishItem(boolean error) {
        PlaylistItem item = getCurrentItem();
        if (item != null) {
            removeItem(item.getItemId(), error ?
                    MediaItemStatus.PLAYBACK_STATE_ERROR :
                        MediaItemStatus.PLAYBACK_STATE_FINISHED);
            updateStatus();
        }
    }

    // set the Player that this playback manager will interact with
    public void setPlayer(Player player) {
        mPlayer = player;
        checkPlayer();
        mPlayer.setCallback(this);
    }

    // provide a callback interface to tell the UI when significant state changes occur
    public void setCallback(Callback callback) {
        mCallback = callback;
    }

    @Override
    public String toString() {
        String result = "Media Queue: ";
        if (!mPlaylist.isEmpty()) {
            for (PlaylistItem item : mPlaylist) {
                result += "\n" + item.toString();
            }
        } else {
            result += "<empty>";
        }
        return result;
    }

    public interface Callback {
        void onStatusChanged();
        void onItemChanged(PlaylistItem item);
    }
}
