/*
 * 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.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteException;
import android.media.MediaDescription;
import android.media.MediaMetadata;
import android.media.browse.MediaBrowser.MediaItem;
import android.media.session.MediaSession.QueueItem;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.MediaStore;
import android.provider.MediaStore.Audio.AlbumColumns;
import android.provider.MediaStore.Audio.AudioColumns;
import android.service.media.MediaBrowserService.Result;
import android.util.Log;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class DataModel {
    private static final String TAG = "LMBDataModel";

    private static final Uri[] ALL_AUDIO_URI = new Uri[] {
            MediaStore.Audio.Media.INTERNAL_CONTENT_URI,
            MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
    };

    private static final Uri[] ALBUMS_URI = new Uri[] {
            MediaStore.Audio.Albums.INTERNAL_CONTENT_URI,
            MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI
    };

    private static final Uri[] ARTISTS_URI = new Uri[] {
            MediaStore.Audio.Artists.INTERNAL_CONTENT_URI,
            MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI
    };

    private static final Uri[] GENRES_URI = new Uri[] {
        MediaStore.Audio.Genres.INTERNAL_CONTENT_URI,
        MediaStore.Audio.Genres.EXTERNAL_CONTENT_URI
    };

    private static final String QUERY_BY_KEY_WHERE_CLAUSE =
            AudioColumns.ALBUM_KEY + "= ? or "
                    + AudioColumns.ARTIST_KEY + " = ? or "
                    + AudioColumns.TITLE_KEY + " = ? or "
                    + AudioColumns.DATA + " like ?";

    private static final String EXTERNAL = "external";
    private static final String INTERNAL = "internal";

    private static final Uri ART_BASE_URI = Uri.parse("content://media/external/audio/albumart");

    public static final String PATH_KEY = "PATH";

    private Context mContext;
    private ContentResolver mResolver;
    private AsyncTask mPendingTask;

    private List<QueueItem> mQueue = new ArrayList<>();

    public DataModel(Context context) {
        mContext = context;
        mResolver = context.getContentResolver();
    }

    public void onQueryByFolder(String parentId, Result<List<MediaItem>> result) {
        FilesystemListTask query = new FilesystemListTask(result, ALL_AUDIO_URI, mResolver);
        queryInBackground(result, query);
    }

    public void onQueryByAlbum(String parentId, Result<List<MediaItem>> result) {
        QueryTask query = new QueryTask.Builder()
                .setResolver(mResolver)
                .setResult(result)
                .setUri(ALBUMS_URI)
                .setKeyColumn(AudioColumns.ALBUM_KEY)
                .setTitleColumn(AudioColumns.ALBUM)
                .setFlags(MediaItem.FLAG_BROWSABLE)
                .build();
        queryInBackground(result, query);
    }

    public void onQueryByArtist(String parentId, Result<List<MediaItem>> result) {
        QueryTask query = new QueryTask.Builder()
                .setResolver(mResolver)
                .setResult(result)
                .setUri(ARTISTS_URI)
                .setKeyColumn(AudioColumns.ARTIST_KEY)
                .setTitleColumn(AudioColumns.ARTIST)
                .setFlags(MediaItem.FLAG_BROWSABLE)
                .build();
        queryInBackground(result, query);
    }

    public void onQueryByGenre(String parentId, Result<List<MediaItem>> result) {
        QueryTask query = new QueryTask.Builder()
                .setResolver(mResolver)
                .setResult(result)
                .setUri(GENRES_URI)
                .setKeyColumn(MediaStore.Audio.Genres._ID)
                .setTitleColumn(MediaStore.Audio.Genres.NAME)
                .setFlags(MediaItem.FLAG_BROWSABLE)
                .build();
        queryInBackground(result, query);
    }

    private void queryInBackground(Result<List<MediaItem>> result,
            AsyncTask<Void, Void, Void> task) {
        result.detach();

        if (mPendingTask != null) {
            mPendingTask.cancel(true);
        }

        mPendingTask = task;
        task.execute();
    }

    public List<QueueItem> getQueue() {
        return mQueue;
    }

    public MediaMetadata getMetadata(String key) {
        Cursor cursor = null;
        MediaMetadata.Builder metadata = new MediaMetadata.Builder();
        try {
            for (Uri uri : ALL_AUDIO_URI) {
                cursor = mResolver.query(uri, null, AudioColumns.TITLE_KEY + " = ?",
                        new String[]{ key }, null);
                if (cursor != null) {
                    int title = cursor.getColumnIndex(AudioColumns.TITLE);
                    int artist = cursor.getColumnIndex(AudioColumns.ARTIST);
                    int album = cursor.getColumnIndex(AudioColumns.ALBUM);
                    int albumId = cursor.getColumnIndex(AudioColumns.ALBUM_ID);
                    int duration = cursor.getColumnIndex(AudioColumns.DURATION);

                    while (cursor.moveToNext()) {
                        metadata.putString(MediaMetadata.METADATA_KEY_TITLE,
                                cursor.getString(title));
                        metadata.putString(MediaMetadata.METADATA_KEY_ARTIST,
                                cursor.getString(artist));
                        metadata.putString(MediaMetadata.METADATA_KEY_ALBUM,
                                cursor.getString(album));
                        metadata.putLong(MediaMetadata.METADATA_KEY_DURATION,
                                cursor.getLong(duration));

                        String albumArt = null;
                        Uri albumArtUri = ContentUris.withAppendedId(ART_BASE_URI,
                                cursor.getLong(albumId));
                        try {
                            InputStream dummy = mResolver.openInputStream(albumArtUri);
                            albumArt = albumArtUri.toString();
                            dummy.close();
                        } catch (IOException e) {
                            // Ignored because the albumArt is intialized correctly anyway.
                        }
                        metadata.putString(MediaMetadata.METADATA_KEY_ALBUM_ART_URI, albumArt);
                        break;
                    }
                }
            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }

        return metadata.build();
    }

    /**
     * Note: This clears out the queue. You should have a local copy of the queue before calling
     * this method.
     */
    public void onQueryByKey(String lastCategory, String parentId, Result<List<MediaItem>> result) {
        mQueue.clear();

        QueryTask.Builder query = new QueryTask.Builder()
                .setResolver(mResolver)
                .setResult(result);

        if (LocalMediaBrowserService.GENRES_ID.equals(lastCategory)) {
            // Genres come from a different table and don't use the where clause from the
            // usual media table so we need to have this condition.
            try {
                long id = Long.parseLong(parentId);
                query.setUri(new Uri[] {
                    MediaStore.Audio.Genres.Members.getContentUri(EXTERNAL, id),
                    MediaStore.Audio.Genres.Members.getContentUri(INTERNAL, id) });
            } catch (NumberFormatException e) {
                // This should never happen.
                Log.e(TAG, "Incorrect key type: " + parentId + ", sending empty result");
                result.sendResult(new ArrayList<MediaItem>());
                return;
            }
        } else {
            query.setUri(ALL_AUDIO_URI)
                    .setWhereClause(QUERY_BY_KEY_WHERE_CLAUSE)
                    .setWhereArgs(new String[] { parentId, parentId, parentId, parentId });
        }

        query.setKeyColumn(AudioColumns.TITLE_KEY)
                .setTitleColumn(AudioColumns.TITLE)
                .setSubtitleColumn(AudioColumns.ALBUM)
                .setFlags(MediaItem.FLAG_PLAYABLE)
                .setQueue(mQueue);
        queryInBackground(result, query.build());
    }

    // This async task is similar enough to all the others that it feels like it can be unified
    // but is different enough that unifying it makes the code for both cases look really weird
    // and over paramterized so at the risk of being a little more verbose, this is separated out
    // in the name of understandability.
    private static class FilesystemListTask extends AsyncTask<Void, Void, Void> {
        private static final String[] COLUMNS = { AudioColumns.DATA };
        private Result<List<MediaItem>> mResult;
        private Uri[] mUris;
        private ContentResolver mResolver;

        public FilesystemListTask(Result<List<MediaItem>> result, Uri[] uris,
                ContentResolver resolver) {
            mResult = result;
            mUris = uris;
            mResolver = resolver;
        }

        @Override
        protected Void doInBackground(Void... voids) {
            Set<String> paths = new HashSet<String>();

            Cursor cursor = null;
            for (Uri uri : mUris) {
                try {
                    cursor = mResolver.query(uri, COLUMNS, null , null, null);
                    if (cursor != null) {
                        int pathColumn = cursor.getColumnIndex(AudioColumns.DATA);

                        while (cursor.moveToNext()) {
                            // We want to de-dupe paths of each of the songs so we get just a list
                            // of containing directories.
                            String fullPath = cursor.getString(pathColumn);
                            int fileNameStart = fullPath.lastIndexOf(File.separator);
                            if (fileNameStart < 0) {
                                continue;
                            }

                            String dirPath = fullPath.substring(0, fileNameStart);
                            paths.add(dirPath);
                        }
                    }
                } catch (SQLiteException e) {
                    Log.e(TAG, "Failed to execute query " + e);  // Stack trace is noisy.
                } finally {
                    if (cursor != null) {
                        cursor.close();
                    }
                }
            }

            // Take the list of deduplicated directories and put them into the results list with
            // the full directory path as the key so we can match on it later.
            List<MediaItem> results = new ArrayList<>();
            for (String path : paths) {
                int dirNameStart = path.lastIndexOf(File.separator) + 1;
                String dirName = path.substring(dirNameStart, path.length());
                MediaDescription description = new MediaDescription.Builder()
                        .setMediaId(path + "%")  // Used in a like query.
                        .setTitle(dirName)
                        .setSubtitle(path)
                        .build();
                results.add(new MediaItem(description, MediaItem.FLAG_BROWSABLE));
            }
            mResult.sendResult(results);
            return null;
        }
    }

    private static class QueryTask extends AsyncTask<Void, Void, Void> {
        private Result<List<MediaItem>> mResult;
        private String[] mColumns;
        private String mWhereClause;
        private String[] mWhereArgs;
        private String mKeyColumn;
        private String mTitleColumn;
        private String mSubtitleColumn;
        private Uri[] mUris;
        private int mFlags;
        private ContentResolver mResolver;
        private List<QueueItem> mQueue;

        private QueryTask(Builder builder) {
            mColumns = builder.mColumns;
            mWhereClause = builder.mWhereClause;
            mWhereArgs = builder.mWhereArgs;
            mKeyColumn = builder.mKeyColumn;
            mTitleColumn = builder.mTitleColumn;
            mUris = builder.mUris;
            mFlags = builder.mFlags;
            mResolver = builder.mResolver;
            mResult = builder.mResult;
            mQueue = builder.mQueue;
            mSubtitleColumn = builder.mSubtitleColumn;
        }

        @Override
        protected Void doInBackground(Void... voids) {
            List<MediaItem> results = new ArrayList<>();

            long idx = 0;

            Cursor cursor = null;
            for (Uri uri : mUris) {
                try {
                    cursor = mResolver.query(uri, mColumns, mWhereClause, mWhereArgs, null);
                    if (cursor != null) {
                        int keyColumn = cursor.getColumnIndex(mKeyColumn);
                        int titleColumn = cursor.getColumnIndex(mTitleColumn);
                        int pathColumn = cursor.getColumnIndex(AudioColumns.DATA);
                        int subtitleColumn = -1;
                        if (mSubtitleColumn != null) {
                            subtitleColumn = cursor.getColumnIndex(mSubtitleColumn);
                        }

                        while (cursor.moveToNext()) {
                            Bundle path = new Bundle();
                            if (pathColumn != -1) {
                                path.putString(PATH_KEY, cursor.getString(pathColumn));
                            }

                            MediaDescription.Builder builder = new MediaDescription.Builder()
                                    .setMediaId(cursor.getString(keyColumn))
                                    .setTitle(cursor.getString(titleColumn))
                                    .setExtras(path);

                            if (subtitleColumn != -1) {
                                builder.setSubtitle(cursor.getString(subtitleColumn));
                            }

                            MediaDescription description = builder.build();
                            results.add(new MediaItem(description, mFlags));

                            // We rebuild the queue here so if the user selects the item then we
                            // can immediately use this queue.
                            if (mQueue != null) {
                                mQueue.add(new QueueItem(description, idx));
                            }
                            idx++;
                        }
                    }
                } catch (SQLiteException e) {
                    // Sometimes tables don't exist if the media scanner hasn't seen data of that
                    // type yet. For example, the genres table doesn't seem to exist at all until
                    // the first time a song with a genre is encountered. If we hit an exception,
                    // the result is never sent causing the other end to hang up, which is a bad
                    // thing. We can instead just be resilient and return an empty list.
                    Log.i(TAG, "Failed to execute query " + e);  // Stack trace is noisy.
                } finally {
                    if (cursor != null) {
                        cursor.close();
                    }
                }
            }

            mResult.sendResult(results);
            return null;  // Ignored.
        }

        //
        // Boilerplate Alert!
        //
        public static class Builder {
            private Result<List<MediaItem>> mResult;
            private String[] mColumns;
            private String mWhereClause;
            private String[] mWhereArgs;
            private String mKeyColumn;
            private String mTitleColumn;
            private String mSubtitleColumn;
            private Uri[] mUris;
            private int mFlags;
            private ContentResolver mResolver;
            private List<QueueItem> mQueue;

            public Builder setColumns(String[] columns) {
                mColumns = columns;
                return this;
            }

            public Builder setWhereClause(String whereClause) {
                mWhereClause = whereClause;
                return this;
            }

            public Builder setWhereArgs(String[] whereArgs) {
                mWhereArgs = whereArgs;
                return this;
            }

            public Builder setUri(Uri[] uris) {
                mUris = uris;
                return this;
            }

            public Builder setKeyColumn(String keyColumn) {
                mKeyColumn = keyColumn;
                return this;
            }

            public Builder setTitleColumn(String titleColumn) {
                mTitleColumn = titleColumn;
                return this;
            }

            public Builder setSubtitleColumn(String subtitleColumn) {
                mSubtitleColumn = subtitleColumn;
                return this;
            }

            public Builder setFlags(int flags) {
                mFlags = flags;
                return this;
            }

            public Builder setResult(Result<List<MediaItem>> result) {
                mResult = result;
                return this;
            }

            public Builder setResolver(ContentResolver resolver) {
                mResolver = resolver;
                return this;
            }

            public Builder setQueue(List<QueueItem> queue) {
                mQueue = queue;
                return this;
            }

            public QueryTask build() {
                if (mUris == null || mKeyColumn == null || mResolver == null ||
                        mResult == null || mTitleColumn == null) {
                    throw new IllegalStateException(
                            "uri, keyColumn, resolver, result and titleColumn are required.");
                }
                return new QueryTask(this);
            }
        }
    }
}
