/*
 * 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.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.MediaDescription;
import android.media.browse.MediaBrowser;
import android.media.session.MediaSession;
import android.os.Bundle;
import android.service.media.MediaBrowserService;
import androidx.annotation.Nullable;
import android.util.Log;

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

public class LocalMediaBrowserService extends MediaBrowserService {
    private static final String TAG = "LMBService";
    private static final String ROOT_ID = "__ROOT__";
    private static final String MEDIA_SESSION_TAG = "LOCAL_MEDIA_SESSION";

    static final String FOLDERS_ID = "__FOLDERS__";
    static final String ARTISTS_ID = "__ARTISTS__";
    static final String ALBUMS_ID = "__ALBUMS__";
    static final String GENRES_ID = "__GENRES__";

    static final String ACTION_PLAY = "com.android.car.media.localmediaplayer.ACTION_PLAY";
    static final String ACTION_PAUSE = "com.android.car.media.localmediaplayer.ACTION_PAUSE";
    static final String ACTION_NEXT = "com.android.car.media.localmediaplayer.ACTION_NEXT";
    static final String ACTION_PREV = "com.android.car.media.localmediaplayer.ACTION_PREV";

    private BrowserRoot mRoot = new BrowserRoot(ROOT_ID, null);
    List<MediaBrowser.MediaItem> mRootItems = new ArrayList<>();

    private DataModel mDataModel;
    private Player mPlayer;
    private MediaSession mSession;
    private String mLastCategory;

    private BroadcastReceiver mNotificationReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction() == null) {
                return;
            }

            switch (intent.getAction()) {
                case ACTION_PLAY:
                    mPlayer.onPlay();
                    break;
                case ACTION_PAUSE:
                    mPlayer.onPause();
                    break;
                case ACTION_NEXT:
                    mPlayer.onSkipToNext();
                    break;
                case ACTION_PREV:
                    mPlayer.onSkipToPrevious();
                    break;
                default:
                    Log.w(TAG, "Ingoring intent with unknown action=" + intent);
            }
        }
    };

    private void addRootItems() {
        MediaDescription folders = new MediaDescription.Builder()
                .setMediaId(FOLDERS_ID)
                .setTitle(getString(R.string.folders_title))
                .setIconUri(Utils.getUriForResource(this, R.drawable.ic_folder))
                .build();
        mRootItems.add(new MediaBrowser.MediaItem(folders, MediaBrowser.MediaItem.FLAG_BROWSABLE));

        MediaDescription albums = new MediaDescription.Builder()
                .setMediaId(ALBUMS_ID)
                .setTitle(getString(R.string.albums_title))
                .setIconUri(Utils.getUriForResource(this, R.drawable.ic_album))
                .build();
        mRootItems.add(new MediaBrowser.MediaItem(albums, MediaBrowser.MediaItem.FLAG_BROWSABLE));

        MediaDescription artists = new MediaDescription.Builder()
                .setMediaId(ARTISTS_ID)
                .setTitle(getString(R.string.artists_title))
                .setIconUri(Utils.getUriForResource(this, R.drawable.ic_artist))
                .build();
        mRootItems.add(new MediaBrowser.MediaItem(artists, MediaBrowser.MediaItem.FLAG_BROWSABLE));

        MediaDescription genres = new MediaDescription.Builder()
                .setMediaId(GENRES_ID)
                .setTitle(getString(R.string.genres_title))
                .setIconUri(Utils.getUriForResource(this, R.drawable.ic_genre))
                .build();
        mRootItems.add(new MediaBrowser.MediaItem(genres, MediaBrowser.MediaItem.FLAG_BROWSABLE));
    }

    @Override
    public void onCreate() {
        super.onCreate();

        mDataModel = new DataModel(this);
        addRootItems();
        mSession = new MediaSession(this, MEDIA_SESSION_TAG);
        setSessionToken(mSession.getSessionToken());
        mPlayer = new Player(this, mSession, mDataModel);
        mSession.setCallback(mPlayer);
        mSession.setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS
                | MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);
        mPlayer.maybeRestoreState();

        IntentFilter filter = new IntentFilter();
        filter.addAction(ACTION_PLAY);
        filter.addAction(ACTION_PAUSE);
        filter.addAction(ACTION_NEXT);
        filter.addAction(ACTION_PREV);
        registerReceiver(mNotificationReceiver, filter, Context.RECEIVER_NOT_EXPORTED);
    }

    @Override
    public void onDestroy() {
        mPlayer.saveState();
        mPlayer.destroy();
        mSession.release();
        unregisterReceiver(mNotificationReceiver);
        super.onDestroy();
    }

    @Nullable
    @Override
    public BrowserRoot onGetRoot(String clientName, int clientUid, Bundle rootHints) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "onGetRoot clientName=" + clientName);
        }
        return mRoot;
    }

    @Override
    public void onLoadChildren(String parentId, Result<List<MediaBrowser.MediaItem>> result) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "onLoadChildren parentId=" + parentId);
        }

        switch (parentId) {
            case ROOT_ID:
                result.sendResult(mRootItems);
                mLastCategory = parentId;
                break;
            case FOLDERS_ID:
                mDataModel.onQueryByFolder(parentId, result);
                mLastCategory = parentId;
                break;
            case ALBUMS_ID:
                mDataModel.onQueryByAlbum(parentId, result);
                mLastCategory = parentId;
                break;
            case ARTISTS_ID:
                mDataModel.onQueryByArtist(parentId, result);
                mLastCategory = parentId;
                break;
            case GENRES_ID:
                mDataModel.onQueryByGenre(parentId, result);
                mLastCategory = parentId;
                break;
            default:
                mDataModel.onQueryByKey(mLastCategory, parentId, result);
        }
    }
}
