/*
 * Copyright (C) 2017 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.music.utils;

import static android.Manifest.permission.READ_EXTERNAL_STORAGE;

import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.media.MediaActionSound;
import android.media.MediaMetadata;
import android.media.MediaMetadataRetriever;
import android.net.Uri;
import android.os.AsyncTask;
import android.provider.MediaStore;
import android.util.Log;
import com.android.music.MediaPlaybackService;
import com.android.music.MusicUtils;
import com.android.music.R;

import java.io.File;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/*
A provider of music contents to the music application, it reads external storage for any music
files, parse them and
store them in this class for future use.
 */
public class MusicProvider {
    private static final String TAG = "MusicProvider";

    // Public constants
    public static final String UNKOWN = "UNKNOWN";
    // Uri source of this track
    public static final String CUSTOM_METADATA_TRACK_SOURCE = "__SOURCE__";
    // Sort key for this tack
    public static final String CUSTOM_METADATA_SORT_KEY = "__SORT_KEY__";

    // Content select criteria
    private static final String MUSIC_SELECT_FILTER = MediaStore.Audio.Media.IS_MUSIC + " != 0";
    private static final String MUSIC_SORT_ORDER = MediaStore.Audio.Media.TITLE + " ASC";

    // Categorized caches for music track data:
    private Context mContext;
    // Album Name --> list of Metadata
    private ConcurrentMap<String, List<MediaMetadata>> mMusicListByAlbum;
    // Playlist Name --> list of Metadata
    private ConcurrentMap<String, List<MediaMetadata>> mMusicListByPlaylist;
    // Artist Name --> Map of (album name --> album metadata)
    private ConcurrentMap<String, Map<String, MediaMetadata>> mArtistAlbumDb;
    private List<MediaMetadata> mMusicList;
    private final ConcurrentMap<Long, Song> mMusicListById;
    private final ConcurrentMap<String, Song> mMusicListByMediaId;

    enum State { NON_INITIALIZED, INITIALIZING, INITIALIZED }

    private volatile State mCurrentState = State.NON_INITIALIZED;

    public MusicProvider(Context context) {
        mContext = context;
        mArtistAlbumDb = new ConcurrentHashMap<>();
        mMusicListByAlbum = new ConcurrentHashMap<>();
        mMusicListByPlaylist = new ConcurrentHashMap<>();
        mMusicListById = new ConcurrentHashMap<>();
        mMusicList = new ArrayList<>();
        mMusicListByMediaId = new ConcurrentHashMap<>();
        mMusicListByPlaylist.put(MediaIDHelper.MEDIA_ID_NOW_PLAYING, new ArrayList<>());
    }

    public boolean isInitialized() {
        return mCurrentState == State.INITIALIZED;
    }

    /**
     * Get an iterator over the list of artists
     *
     * @return list of artists
     */
    public Iterable<String> getArtists() {
        if (mCurrentState != State.INITIALIZED) {
            return Collections.emptyList();
        }
        return mArtistAlbumDb.keySet();
    }

    /**
     * Get an iterator over the list of albums
     *
     * @return list of albums
     */
    public Iterable<MediaMetadata> getAlbums() {
        if (mCurrentState != State.INITIALIZED) {
            return Collections.emptyList();
        }
        ArrayList<MediaMetadata> albumList = new ArrayList<>();
        for (Map<String, MediaMetadata> artist_albums : mArtistAlbumDb.values()) {
            albumList.addAll(artist_albums.values());
        }
        return albumList;
    }

    /**
     * Get an iterator over the list of playlists
     *
     * @return list of playlists
     */
    public Iterable<String> getPlaylists() {
        if (mCurrentState != State.INITIALIZED) {
            return Collections.emptyList();
        }
        return mMusicListByPlaylist.keySet();
    }

    public Iterable<MediaMetadata> getMusicList() {
        return mMusicList;
    }

    /**
     * Get albums of a certain artist
     *
     */
    public Iterable<MediaMetadata> getAlbumByArtist(String artist) {
        if (mCurrentState != State.INITIALIZED || !mArtistAlbumDb.containsKey(artist)) {
            return Collections.emptyList();
        }
        return mArtistAlbumDb.get(artist).values();
    }

    /**
     * Get music tracks of the given album
     *
     */
    public Iterable<MediaMetadata> getMusicsByAlbum(String album) {
        if (mCurrentState != State.INITIALIZED || !mMusicListByAlbum.containsKey(album)) {
            return Collections.emptyList();
        }
        return mMusicListByAlbum.get(album);
    }

    /**
     * Get music tracks of the given playlist
     *
     */
    public Iterable<MediaMetadata> getMusicsByPlaylist(String playlist) {
        if (mCurrentState != State.INITIALIZED || !mMusicListByPlaylist.containsKey(playlist)) {
            return Collections.emptyList();
        }
        return mMusicListByPlaylist.get(playlist);
    }

    /**
     * Return the MediaMetadata for the given musicID.
     *
     * @param musicId The unique, non-hierarchical music ID.
     */
    public Song getMusicById(long musicId) {
        return mMusicListById.containsKey(musicId) ? mMusicListById.get(musicId) : null;
    }

    /**
     * Return the MediaMetadata for the given musicID.
     *
     * @param musicId The unique, non-hierarchical music ID.
     */
    public Song getMusicByMediaId(String musicId) {
        return mMusicListByMediaId.containsKey(musicId) ? mMusicListByMediaId.get(musicId) : null;
    }

    /**
     * Very basic implementation of a search that filter music tracks which title containing
     * the given query.
     *
     */
    public Iterable<MediaMetadata> searchMusic(String titleQuery) {
        if (mCurrentState != State.INITIALIZED) {
            return Collections.emptyList();
        }
        ArrayList<MediaMetadata> result = new ArrayList<>();
        titleQuery = titleQuery.toLowerCase();
        for (Song song : mMusicListByMediaId.values()) {
            if (song.getMetadata()
                            .getString(MediaMetadata.METADATA_KEY_TITLE)
                            .toLowerCase()
                            .contains(titleQuery)) {
                result.add(song.getMetadata());
            }
        }
        return result;
    }

    public interface MusicProviderCallback { void onMusicCatalogReady(boolean success); }

    /**
     * Get the list of music tracks from disk and caches the track information
     * for future reference, keying tracks by musicId and grouping by genre.
     */
    public void retrieveMediaAsync(final MusicProviderCallback callback) {
        Log.d(TAG, "retrieveMediaAsync called");
        if (mCurrentState == State.INITIALIZED) {
            // Nothing to do, execute callback immediately
            callback.onMusicCatalogReady(true);
            return;
        }

        // Asynchronously load the music catalog in a separate thread
        new AsyncTask<Void, Void, State>() {
            @Override
            protected State doInBackground(Void... params) {
                if (mCurrentState == State.INITIALIZED) {
                    return mCurrentState;
                }
                mCurrentState = State.INITIALIZING;
                if (retrieveMedia()) {
                    mCurrentState = State.INITIALIZED;
                } else {
                    mCurrentState = State.NON_INITIALIZED;
                }
                return mCurrentState;
            }

            @Override
            protected void onPostExecute(State current) {
                if (callback != null) {
                    callback.onMusicCatalogReady(current == State.INITIALIZED);
                }
            }
        }
                .execute();
    }

    public synchronized boolean retrieveAllPlayLists() {
        Cursor cursor = mContext.getContentResolver().query(
                MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI, null, null, null, null);
        if (cursor == null) {
            Log.e(TAG, "Failed to retreive playlist: cursor is null");
            return false;
        }
        if (!cursor.moveToFirst()) {
            Log.d(TAG, "Failed to move cursor to first row (no query result)");
            cursor.close();
            return true;
        }
        int idColumn = cursor.getColumnIndex(MediaStore.Audio.Playlists._ID);
        int nameColumn = cursor.getColumnIndex(MediaStore.Audio.Playlists.NAME);
        int pathColumn = cursor.getColumnIndex(MediaStore.Audio.Playlists.DATA);
        do {
            long thisId = cursor.getLong(idColumn);
            String thisPath = cursor.getString(pathColumn);
            String thisName = cursor.getString(nameColumn);
            Log.i(TAG, "PlayList ID: " + thisId + " Name: " + thisName);
            List<MediaMetadata> songList = retreivePlaylistMetadata(thisId, thisPath);
            LogHelper.i(TAG, "Found ", songList.size(), " items for playlist name: ", thisName);
            mMusicListByPlaylist.put(thisName, songList);
        } while (cursor.moveToNext());
        cursor.close();
        return true;
    }

    public synchronized List<MediaMetadata> retreivePlaylistMetadata(
            long playlistId, String playlistPath) {
        Cursor cursor = mContext.getContentResolver().query(Uri.parse(playlistPath), null,
                MediaStore.Audio.Playlists.Members.PLAYLIST_ID + " == " + playlistId, null, null);
        if (cursor == null) {
            Log.e(TAG, "Failed to retreive individual playlist: cursor is null");
            return null;
        }
        if (!cursor.moveToFirst()) {
            Log.d(TAG, "Failed to move cursor to first row (no query result for playlist)");
            cursor.close();
            return null;
        }
        List<Song> songList = new ArrayList<>();
        int idColumn = cursor.getColumnIndex(MediaStore.Audio.Playlists.Members._ID);
        int audioIdColumn = cursor.getColumnIndex(MediaStore.Audio.Playlists.Members.AUDIO_ID);
        int orderColumn = cursor.getColumnIndex(MediaStore.Audio.Playlists.Members.PLAY_ORDER);
        int audioPathColumn = cursor.getColumnIndex(MediaStore.Audio.Playlists.Members.DATA);
        int audioNameColumn = cursor.getColumnIndex(MediaStore.Audio.Playlists.Members.TITLE);
        do {
            long thisId = cursor.getLong(idColumn);
            long thisAudioId = cursor.getLong(audioIdColumn);
            long thisOrder = cursor.getLong(orderColumn);
            String thisAudioPath = cursor.getString(audioPathColumn);
            Log.i(TAG,
                    "Playlist ID: " + playlistId + " Music ID: " + thisAudioId
                            + " Name: " + audioNameColumn);
            if (!mMusicListById.containsKey(thisAudioId)) {
                LogHelper.d(TAG, "Music does not exist");
                continue;
            }
            Song song = mMusicListById.get(thisAudioId);
            song.setSortKey(thisOrder);
            songList.add(song);
        } while (cursor.moveToNext());
        cursor.close();
        songList.sort(new Comparator<Song>() {
            @Override
            public int compare(Song s1, Song s2) {
                long key1 = s1.getSortKey();
                long key2 = s2.getSortKey();
                if (key1 < key2) {
                    return -1;
                } else if (key1 == key2) {
                    return 0;
                } else {
                    return 1;
                }
            }
        });
        List<MediaMetadata> metadataList = new ArrayList<>();
        for (Song song : songList) {
            metadataList.add(song.getMetadata());
        }
        return metadataList;
    }

    private synchronized boolean retrieveMedia() {
        if (mContext.checkSelfPermission(READ_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {
            return false;
        }

        Cursor cursor =
                mContext.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
                        null, MUSIC_SELECT_FILTER, null, MUSIC_SORT_ORDER);
        if (cursor == null) {
            Log.e(TAG, "Failed to retreive music: cursor is null");
            mCurrentState = State.NON_INITIALIZED;
            return false;
        }
        if (!cursor.moveToFirst()) {
            Log.d(TAG, "Failed to move cursor to first row (no query result)");
            cursor.close();
            return true;
        }
        int idColumn = cursor.getColumnIndex(MediaStore.Audio.Media._ID);
        int titleColumn = cursor.getColumnIndex(MediaStore.Audio.Media.TITLE);
        int pathColumn = cursor.getColumnIndex(MediaStore.Audio.Media.DATA);
        do {
            Log.i(TAG,
                    "Music ID: " + cursor.getString(idColumn)
                            + " Title: " + cursor.getString(titleColumn));
            long thisId = cursor.getLong(idColumn);
            String thisPath = cursor.getString(pathColumn);
            MediaMetadata metadata = retrievMediaMetadata(thisId, thisPath);
            Log.i(TAG, "MediaMetadata: " + metadata);
            if (metadata == null) {
                continue;
            }
            Song thisSong = new Song(thisId, metadata, null);
            // Construct per feature database
            mMusicList.add(metadata);
            mMusicListById.put(thisId, thisSong);
            mMusicListByMediaId.put(String.valueOf(thisId), thisSong);
            addMusicToAlbumList(metadata);
            addMusicToArtistList(metadata);
        } while (cursor.moveToNext());
        cursor.close();
        return true;
    }

    private synchronized MediaMetadata retrievMediaMetadata(long musicId, String musicPath) {
        LogHelper.d(TAG, "getting metadata for music: ", musicPath);
        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
        Uri contentUri = ContentUris.withAppendedId(
                android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, musicId);
        if (!(new File(musicPath).exists())) {
            LogHelper.d(TAG, "Does not exist, deleting item");
            mContext.getContentResolver().delete(contentUri, null, null);
            return null;
        }
        retriever.setDataSource(mContext, contentUri);
        String title = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
        String album = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM);
        String artist = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
        String durationString =
                retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
        long duration = durationString != null ? Long.parseLong(durationString) : 0;
        MediaMetadata.Builder metadataBuilder =
                new MediaMetadata.Builder()
                        .putString(MediaMetadata.METADATA_KEY_MEDIA_ID, String.valueOf(musicId))
                        .putString(CUSTOM_METADATA_TRACK_SOURCE, musicPath)
                        .putString(MediaMetadata.METADATA_KEY_TITLE, title != null ? title : UNKOWN)
                        .putString(MediaMetadata.METADATA_KEY_ALBUM, album != null ? album : UNKOWN)
                        .putString(
                                MediaMetadata.METADATA_KEY_ARTIST, artist != null ? artist : UNKOWN)
                        .putLong(MediaMetadata.METADATA_KEY_DURATION, duration);
        byte[] albumArtData = retriever.getEmbeddedPicture();
        Bitmap bitmap;
        if (albumArtData != null) {
            bitmap = BitmapFactory.decodeByteArray(albumArtData, 0, albumArtData.length);
            bitmap = MusicUtils.resizeBitmap(bitmap, getDefaultAlbumArt());
            metadataBuilder.putBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART, bitmap);
        }
        retriever.release();
        return metadataBuilder.build();
    }

    private Bitmap getDefaultAlbumArt() {
        BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
        return BitmapFactory.decodeStream(
                mContext.getResources().openRawResource(R.drawable.albumart_mp_unknown), null,
                opts);
    }

    private void addMusicToAlbumList(MediaMetadata metadata) {
        String thisAlbum = metadata.getString(MediaMetadata.METADATA_KEY_ALBUM);
        if (thisAlbum == null) {
            thisAlbum = UNKOWN;
        }
        if (!mMusicListByAlbum.containsKey(thisAlbum)) {
            mMusicListByAlbum.put(thisAlbum, new ArrayList<>());
        }
        mMusicListByAlbum.get(thisAlbum).add(metadata);
    }

    private void addMusicToArtistList(MediaMetadata metadata) {
        String thisArtist = metadata.getString(MediaMetadata.METADATA_KEY_ARTIST);
        if (thisArtist == null) {
            thisArtist = UNKOWN;
        }
        String thisAlbum = metadata.getString(MediaMetadata.METADATA_KEY_ALBUM);
        if (thisAlbum == null) {
            thisAlbum = UNKOWN;
        }
        if (!mArtistAlbumDb.containsKey(thisArtist)) {
            mArtistAlbumDb.put(thisArtist, new ConcurrentHashMap<>());
        }
        Map<String, MediaMetadata> albumsMap = mArtistAlbumDb.get(thisArtist);
        MediaMetadata.Builder builder;
        long count = 0;
        Bitmap thisAlbumArt = metadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART);
        if (albumsMap.containsKey(thisAlbum)) {
            MediaMetadata album_metadata = albumsMap.get(thisAlbum);
            count = album_metadata.getLong(MediaMetadata.METADATA_KEY_NUM_TRACKS);
            Bitmap nAlbumArt = album_metadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART);
            builder = new MediaMetadata.Builder(album_metadata);
            if (nAlbumArt != null) {
                thisAlbumArt = null;
            }
        } else {
            builder = new MediaMetadata.Builder();
            builder.putString(MediaMetadata.METADATA_KEY_ALBUM, thisAlbum)
                    .putString(MediaMetadata.METADATA_KEY_ARTIST, thisArtist);
        }
        if (thisAlbumArt != null) {
            builder.putBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART, thisAlbumArt);
        }
        builder.putLong(MediaMetadata.METADATA_KEY_NUM_TRACKS, count + 1);
        albumsMap.put(thisAlbum, builder.build());
    }

    public synchronized void updateMusic(String musicId, MediaMetadata metadata) {
        Song song = mMusicListByMediaId.get(musicId);
        if (song == null) {
            return;
        }

        String oldGenre = song.getMetadata().getString(MediaMetadata.METADATA_KEY_GENRE);
        String newGenre = metadata.getString(MediaMetadata.METADATA_KEY_GENRE);

        song.setMetadata(metadata);

        // if genre has changed, we need to rebuild the list by genre
        if (!oldGenre.equals(newGenre)) {
            //            buildListsByGenre();
        }
    }
}
