/*
 * 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.android.providers.downloads;

import android.app.DownloadManager;
import android.app.DownloadManager.Query;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.database.MatrixCursor.RowBuilder;
import android.graphics.Point;
import android.net.Uri;
import android.os.Binder;
import android.os.CancellationSignal;
import android.os.Environment;
import android.os.FileObserver;
import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
import android.provider.DocumentsContract.Path;
import android.provider.DocumentsContract.Root;
import android.provider.Downloads;
import android.text.TextUtils;
import android.util.Log;

import com.android.internal.content.FileSystemProvider;

import libcore.io.IoUtils;

import java.io.File;
import java.io.FileNotFoundException;
import java.text.NumberFormat;
import java.util.HashSet;
import java.util.Set;

import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;

/**
 * Presents files located in {@link Environment#DIRECTORY_DOWNLOADS} and contents from
 * {@link DownloadManager}. {@link DownloadManager} contents include active downloads and completed
 * downloads added by other applications using
 * {@link DownloadManager#addCompletedDownload(String, String, boolean, String, String, long, boolean, boolean, Uri, Uri)}
 * .
 */
public class DownloadStorageProvider extends FileSystemProvider {
    private static final String TAG = "DownloadStorageProvider";
    private static final boolean DEBUG = false;

    private static final String AUTHORITY = Constants.STORAGE_AUTHORITY;
    private static final String DOC_ID_ROOT = Constants.STORAGE_ROOT_ID;

    private static final String[] DEFAULT_ROOT_PROJECTION = new String[] {
            Root.COLUMN_ROOT_ID, Root.COLUMN_FLAGS, Root.COLUMN_ICON,
            Root.COLUMN_TITLE, Root.COLUMN_DOCUMENT_ID,
    };

    private static final String[] DEFAULT_DOCUMENT_PROJECTION = new String[] {
            Document.COLUMN_DOCUMENT_ID, Document.COLUMN_MIME_TYPE, Document.COLUMN_DISPLAY_NAME,
            Document.COLUMN_SUMMARY, Document.COLUMN_LAST_MODIFIED, Document.COLUMN_FLAGS,
            Document.COLUMN_SIZE,
    };

    private DownloadManager mDm;

    @Override
    public boolean onCreate() {
        super.onCreate(DEFAULT_DOCUMENT_PROJECTION);
        mDm = (DownloadManager) getContext().getSystemService(Context.DOWNLOAD_SERVICE);
        mDm.setAccessAllDownloads(true);
        mDm.setAccessFilename(true);

        return true;
    }

    private static String[] resolveRootProjection(String[] projection) {
        return projection != null ? projection : DEFAULT_ROOT_PROJECTION;
    }

    private static String[] resolveDocumentProjection(String[] projection) {
        return projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION;
    }

    private void copyNotificationUri(MatrixCursor result, Cursor cursor) {
        result.setNotificationUri(getContext().getContentResolver(), cursor.getNotificationUri());
    }

    /**
     * Called by {@link DownloadProvider} when deleting a row in the {@link DownloadManager}
     * database.
     */
    static void onDownloadProviderDelete(Context context, long id) {
        final Uri uri = DocumentsContract.buildDocumentUri(AUTHORITY, Long.toString(id));
        context.revokeUriPermission(uri, ~0);
    }

    @Override
    public Cursor queryRoots(String[] projection) throws FileNotFoundException {
        // It's possible that the folder does not exist on disk, so we will create the folder if
        // that is the case. If user decides to delete the folder later, then it's OK to fail on
        // subsequent queries.
        getDownloadsDirectory().mkdirs();

        final MatrixCursor result = new MatrixCursor(resolveRootProjection(projection));
        final RowBuilder row = result.newRow();
        row.add(Root.COLUMN_ROOT_ID, DOC_ID_ROOT);
        row.add(Root.COLUMN_FLAGS, Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_RECENTS
                | Root.FLAG_SUPPORTS_CREATE | Root.FLAG_SUPPORTS_SEARCH
                | Root.FLAG_SUPPORTS_IS_CHILD);
        row.add(Root.COLUMN_ICON, R.mipmap.ic_launcher_download);
        row.add(Root.COLUMN_TITLE, getContext().getString(R.string.root_downloads));
        row.add(Root.COLUMN_DOCUMENT_ID, DOC_ID_ROOT);
        return result;
    }

    @Override
    public Path findDocumentPath(@Nullable String parentDocId, String docId) throws FileNotFoundException {

        // parentDocId is null if the client is asking for the path to the root of a doc tree.
        // Don't share root information with those who shouldn't know it.
        final String rootId = (parentDocId == null) ? DOC_ID_ROOT : null;

        if (parentDocId == null) {
            parentDocId = DOC_ID_ROOT;
        }

        final File parent = getFileForDocId(parentDocId);

        final File doc = getFileForDocId(docId);

        return new Path(rootId, findDocumentPath(parent, doc));
    }

    /**
     * Calls on {@link FileSystemProvider#createDocument(String, String, String)}, and then creates
     * a new database entry in {@link DownloadManager} if it is not a raw file and not a folder.
     */
    @Override
    public String createDocument(String parentDocId, String mimeType, String displayName)
            throws FileNotFoundException {
        // Delegate to real provider
        final long token = Binder.clearCallingIdentity();
        try {
            String newDocumentId = super.createDocument(parentDocId, mimeType, displayName);
            if (!Document.MIME_TYPE_DIR.equals(mimeType)
                    && !RawDocumentsHelper.isRawDocId(parentDocId)) {
                File newFile = getFileForDocId(newDocumentId);
                newDocumentId = Long.toString(mDm.addCompletedDownload(
                        newFile.getName(), newFile.getName(), true, mimeType,
                        newFile.getAbsolutePath(), 0L,
                        false, true));
            }
            return newDocumentId;
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    @Override
    public void deleteDocument(String docId) throws FileNotFoundException {
        // Delegate to real provider
        final long token = Binder.clearCallingIdentity();
        try {
            if (RawDocumentsHelper.isRawDocId(docId)) {
                super.deleteDocument(docId);
                return;
            }
            if (mDm.remove(Long.parseLong(docId)) != 1) {
                throw new IllegalStateException("Failed to delete " + docId);
            }
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    @Override
    public String renameDocument(String docId, String displayName)
            throws FileNotFoundException {
        final long token = Binder.clearCallingIdentity();

        try {
            if (RawDocumentsHelper.isRawDocId(docId)) {
                return super.renameDocument(docId, displayName);
            }

            displayName = FileUtils.buildValidFatFilename(displayName);
            final long id = Long.parseLong(docId);
            if (!mDm.rename(getContext(), id, displayName)) {
                throw new IllegalStateException(
                        "Failed to rename to " + displayName + " in downloadsManager");
            }
            return null;
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    @Override
    public Cursor queryDocument(String docId, String[] projection) throws FileNotFoundException {
        // Delegate to real provider
        final long token = Binder.clearCallingIdentity();
        Cursor cursor = null;
        try {
            if (RawDocumentsHelper.isRawDocId(docId)) {
                return super.queryDocument(docId, projection);
            }

            final DownloadsCursor result = new DownloadsCursor(projection,
                    getContext().getContentResolver());

            if (DOC_ID_ROOT.equals(docId)) {
                includeDefaultDocument(result);
            } else {
                cursor = mDm.query(new Query().setFilterById(Long.parseLong(docId)));
                copyNotificationUri(result, cursor);
                Set<String> filePaths = new HashSet<>();
                if (cursor.moveToFirst()) {
                    // We don't know if this queryDocument() call is from Downloads (manage)
                    // or Files. Safely assume it's Files.
                    includeDownloadFromCursor(result, cursor, filePaths);
                }
            }
            result.start();
            return result;
        } finally {
            IoUtils.closeQuietly(cursor);
            Binder.restoreCallingIdentity(token);
        }
    }

    @Override
    public Cursor queryChildDocuments(String parentDocId, String[] projection, String sortOrder)
            throws FileNotFoundException {
        return queryChildDocuments(parentDocId, projection, sortOrder, false);
    }

    @Override
    public Cursor queryChildDocumentsForManage(
            String parentDocId, String[] projection, String sortOrder)
            throws FileNotFoundException {
        return queryChildDocuments(parentDocId, projection, sortOrder, true);
    }

    private Cursor queryChildDocuments(String parentDocId, String[] projection,
            String sortOrder, boolean manage) throws FileNotFoundException {

        // Delegate to real provider
        final long token = Binder.clearCallingIdentity();
        Cursor cursor = null;
        try {
            if (RawDocumentsHelper.isRawDocId(parentDocId)) {
                return super.queryChildDocuments(parentDocId, projection, sortOrder);
            }

            assert (DOC_ID_ROOT.equals(parentDocId));
            final DownloadsCursor result = new DownloadsCursor(projection,
                    getContext().getContentResolver());
            if (manage) {
                cursor = mDm.query(
                        new DownloadManager.Query().setOnlyIncludeVisibleInDownloadsUi(true));
            } else {
                cursor = mDm
                        .query(new DownloadManager.Query().setOnlyIncludeVisibleInDownloadsUi(true)
                                .setFilterByStatus(DownloadManager.STATUS_SUCCESSFUL));
            }
            copyNotificationUri(result, cursor);
            Set<String> filePaths = new HashSet<>();
            while (cursor.moveToNext()) {
                includeDownloadFromCursor(result, cursor, filePaths);
            }
            includeFilesFromSharedStorage(result, filePaths, null);

            result.start();
            return result;
        } finally {
            IoUtils.closeQuietly(cursor);
            Binder.restoreCallingIdentity(token);
        }
    }

    @Override
    public Cursor queryRecentDocuments(String rootId, String[] projection)
            throws FileNotFoundException {
        final DownloadsCursor result =
                new DownloadsCursor(projection, getContext().getContentResolver());

        // Delegate to real provider
        final long token = Binder.clearCallingIdentity();
        Cursor cursor = null;
        try {
            cursor = mDm.query(new DownloadManager.Query().setOnlyIncludeVisibleInDownloadsUi(true)
                    .setFilterByStatus(DownloadManager.STATUS_SUCCESSFUL));
            copyNotificationUri(result, cursor);
            while (cursor.moveToNext() && result.getCount() < 12) {
                final String mimeType = cursor.getString(
                        cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_MEDIA_TYPE));
                final String uri = cursor.getString(
                        cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_MEDIAPROVIDER_URI));

                // Skip images that have been inserted into the MediaStore so we
                // don't duplicate them in the recents list.
                if (mimeType == null
                        || (mimeType.startsWith("image/") && !TextUtils.isEmpty(uri))) {
                    continue;
                }
            }
        } finally {
            IoUtils.closeQuietly(cursor);
            Binder.restoreCallingIdentity(token);
        }

        result.start();
        return result;
    }

    @Override
    public Cursor querySearchDocuments(String rootId, String query, String[] projection)
            throws FileNotFoundException {

        final DownloadsCursor result =
                new DownloadsCursor(projection, getContext().getContentResolver());

        // Delegate to real provider
        final long token = Binder.clearCallingIdentity();
        Cursor cursor = null;
        try {
            cursor = mDm.query(new DownloadManager.Query().setOnlyIncludeVisibleInDownloadsUi(true)
                    .setFilterByString(query));
            copyNotificationUri(result, cursor);
            Set<String> filePaths = new HashSet<>();
            while (cursor.moveToNext()) {
                includeDownloadFromCursor(result, cursor, filePaths);
            }
            Cursor rawFilesCursor = super.querySearchDocuments(getDownloadsDirectory(), query,
                    projection, filePaths);
            while (rawFilesCursor.moveToNext()) {
                String docId = rawFilesCursor.getString(
                        rawFilesCursor.getColumnIndexOrThrow(Document.COLUMN_DOCUMENT_ID));
                File rawFile = getFileForDocId(docId);
                includeFileFromSharedStorage(result, rawFile);
            }
        } finally {
            IoUtils.closeQuietly(cursor);
            Binder.restoreCallingIdentity(token);
        }

        result.start();
        return result;
    }

    @Override
    public String getDocumentType(String docId) throws FileNotFoundException {
        // Delegate to real provider
        final long token = Binder.clearCallingIdentity();
        try {
            if (RawDocumentsHelper.isRawDocId(docId)) {
                return super.getDocumentType(docId);
            }

            final long id = Long.parseLong(docId);
            final ContentResolver resolver = getContext().getContentResolver();
            return resolver.getType(mDm.getDownloadUri(id));
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    @Override
    public ParcelFileDescriptor openDocument(String docId, String mode, CancellationSignal signal)
            throws FileNotFoundException {
        // Delegate to real provider
        final long token = Binder.clearCallingIdentity();
        try {
            if (RawDocumentsHelper.isRawDocId(docId)) {
                return super.openDocument(docId, mode, signal);
            }

            final long id = Long.parseLong(docId);
            final ContentResolver resolver = getContext().getContentResolver();
            return resolver.openFileDescriptor(mDm.getDownloadUri(id), mode, signal);
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    @Override
    protected File getFileForDocId(String docId, boolean visible) throws FileNotFoundException {
        if (RawDocumentsHelper.isRawDocId(docId)) {
            return new File(RawDocumentsHelper.getAbsoluteFilePath(docId));
        }

        if (DOC_ID_ROOT.equals(docId)) {
            return getDownloadsDirectory();
        }

        final long token = Binder.clearCallingIdentity();
        Cursor cursor = null;
        String localFilePath = null;
        try {
            cursor = mDm.query(new Query().setFilterById(Long.parseLong(docId)));
            if (cursor.moveToFirst()) {
                localFilePath = cursor.getString(
                        cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_LOCAL_FILENAME));
            }
        } finally {
            IoUtils.closeQuietly(cursor);
            Binder.restoreCallingIdentity(token);
        }

        if (localFilePath == null) {
            throw new IllegalStateException("File has no filepath. Could not be found.");
        }
        return new File(localFilePath);
    }

    @Override
    protected String getDocIdForFile(File file) throws FileNotFoundException {
        return RawDocumentsHelper.getDocIdForFile(file);
    }

    @Override
    protected Uri buildNotificationUri(String docId) {
        return DocumentsContract.buildChildDocumentsUri(AUTHORITY, docId);
    }

    private void includeDefaultDocument(MatrixCursor result) {
        final RowBuilder row = result.newRow();
        row.add(Document.COLUMN_DOCUMENT_ID, DOC_ID_ROOT);
        // We have the same display name as our root :)
        row.add(Document.COLUMN_DISPLAY_NAME,
                getContext().getString(R.string.root_downloads));
        row.add(Document.COLUMN_MIME_TYPE, Document.MIME_TYPE_DIR);
        row.add(Document.COLUMN_FLAGS,
                Document.FLAG_DIR_PREFERS_LAST_MODIFIED | Document.FLAG_DIR_SUPPORTS_CREATE);
    }

    /**
     * Adds the entry from the cursor to the result only if the entry is valid. That is,
     * if the file exists in the file system.
     */
    private void includeDownloadFromCursor(MatrixCursor result, Cursor cursor,
            Set<String> filePaths) {
        final long id = cursor.getLong(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_ID));
        final String docId = String.valueOf(id);

        final String displayName = cursor.getString(
                cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_TITLE));
        String summary = cursor.getString(
                cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_DESCRIPTION));
        String mimeType = cursor.getString(
                cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_MEDIA_TYPE));
        if (mimeType == null) {
            // Provide fake MIME type so it's openable
            mimeType = "vnd.android.document/file";
        }
        Long size = cursor.getLong(
                cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
        if (size == -1) {
            size = null;
        }
        String localFilePath = cursor.getString(
                cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_LOCAL_FILENAME));

        int extraFlags = Document.FLAG_PARTIAL;
        final int status = cursor.getInt(
                cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS));
        switch (status) {
            case DownloadManager.STATUS_SUCCESSFUL:
                // Verify that the document still exists in external storage. This is necessary
                // because files can be deleted from the file system without their entry being
                // removed from DownloadsManager.
                if (localFilePath == null || !new File(localFilePath).exists()) {
                    return;
                }
                extraFlags = Document.FLAG_SUPPORTS_RENAME;  // only successful is non-partial
                break;
            case DownloadManager.STATUS_PAUSED:
                summary = getContext().getString(R.string.download_queued);
                break;
            case DownloadManager.STATUS_PENDING:
                summary = getContext().getString(R.string.download_queued);
                break;
            case DownloadManager.STATUS_RUNNING:
                final long progress = cursor.getLong(cursor.getColumnIndexOrThrow(
                        DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
                if (size != null) {
                    String percent =
                            NumberFormat.getPercentInstance().format((double) progress / size);
                    summary = getContext().getString(R.string.download_running_percent, percent);
                } else {
                    summary = getContext().getString(R.string.download_running);
                }
                break;
            case DownloadManager.STATUS_FAILED:
            default:
                summary = getContext().getString(R.string.download_error);
                break;
        }

        int flags = Document.FLAG_SUPPORTS_DELETE | Document.FLAG_SUPPORTS_WRITE | extraFlags;
        if (mimeType.startsWith("image/")) {
            flags |= Document.FLAG_SUPPORTS_THUMBNAIL;
        }

        if (typeSupportsMetadata(mimeType)) {
            flags |= Document.FLAG_SUPPORTS_METADATA;
        }

        final long lastModified = cursor.getLong(
                cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_LAST_MODIFIED_TIMESTAMP));

        final RowBuilder row = result.newRow();
        row.add(Document.COLUMN_DOCUMENT_ID, docId);
        row.add(Document.COLUMN_DISPLAY_NAME, displayName);
        row.add(Document.COLUMN_SUMMARY, summary);
        row.add(Document.COLUMN_SIZE, size);
        row.add(Document.COLUMN_MIME_TYPE, mimeType);
        row.add(Document.COLUMN_FLAGS, flags);
        // Incomplete downloads get a null timestamp.  This prevents thrashy UI when a bunch of
        // active downloads get sorted by mod time.
        if (status != DownloadManager.STATUS_RUNNING) {
            row.add(Document.COLUMN_LAST_MODIFIED, lastModified);
        }
        filePaths.add(localFilePath);
    }

    /**
     * Takes all the top-level files from the Downloads directory and adds them to the result.
     *
     * @param result cursor containing all documents to be returned by queryChildDocuments or
     *            queryChildDocumentsForManage.
     * @param downloadedFilePaths The absolute file paths of all the files in the result Cursor.
     * @param searchString query used to filter out unwanted results.
     */
    private void includeFilesFromSharedStorage(MatrixCursor result,
            Set<String> downloadedFilePaths, @Nullable String searchString)
            throws FileNotFoundException {
        File downloadsDir = getDownloadsDirectory();
        // Add every file from the Downloads directory to the result cursor. Ignore files that
        // were in the supplied downloaded file paths.
        for (File file : downloadsDir.listFiles()) {
            boolean inResultsAlready = downloadedFilePaths.contains(file.getAbsolutePath());
            boolean containsQuery = searchString == null || file.getName().contains(searchString);
            if (!inResultsAlready && containsQuery) {
                includeFileFromSharedStorage(result, file);
            }
        }
    }

    /**
     * Adds a file to the result cursor. It uses a combination of {@code #RAW_PREFIX} and its
     * absolute file path for its id. Directories are not to be included.
     *
     * @param result cursor containing all documents to be returned by queryChildDocuments or
     *            queryChildDocumentsForManage.
     * @param file file to be included in the result cursor.
     */
    private void includeFileFromSharedStorage(MatrixCursor result, File file)
            throws FileNotFoundException {
        includeFile(result, null, file);
    }

    private static File getDownloadsDirectory() {
        return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
    }

    /**
     * A MatrixCursor that spins up a file observer when the first instance is
     * started ({@link #start()}, and stops the file observer when the last instance
     * closed ({@link #close()}. When file changes are observed, a content change
     * notification is sent on the Downloads content URI.
     *
     * <p>This is necessary as other processes, like ExternalStorageProvider,
     * can access and modify files directly (without sending operations
     * through DownloadStorageProvider).
     *
     * <p>Without this, contents accessible by one a Downloads cursor instance
     * (like the Downloads root in Files app) can become state.
     */
    private static final class DownloadsCursor extends MatrixCursor {

        private static final Object mLock = new Object();
        @GuardedBy("mLock")
        private static int mOpenCursorCount = 0;
        @GuardedBy("mLock")
        private static @Nullable ContentChangedRelay mFileWatcher;

        private final ContentResolver mResolver;

        DownloadsCursor(String[] projection, ContentResolver resolver) {
            super(resolveDocumentProjection(projection));
            mResolver = resolver;
        }

        void start() {
            synchronized (mLock) {
                if (mOpenCursorCount++ == 0) {
                    mFileWatcher = new ContentChangedRelay(mResolver);
                    mFileWatcher.startWatching();
                }
            }
        }

        @Override
        public void close() {
            super.close();
            synchronized (mLock) {
                if (--mOpenCursorCount == 0) {
                    mFileWatcher.stopWatching();
                    mFileWatcher = null;
                }
            }
        }
    }

    /**
     * A file observer that notifies on the Downloads content URI(s) when
     * files change on disk.
     */
    private static class ContentChangedRelay extends FileObserver {
        private static final int NOTIFY_EVENTS = ATTRIB | CLOSE_WRITE | MOVED_FROM | MOVED_TO
                | CREATE | DELETE | DELETE_SELF | MOVE_SELF;

        private static final String DOWNLOADS_PATH = getDownloadsDirectory().getAbsolutePath();
        private final ContentResolver mResolver;

        public ContentChangedRelay(ContentResolver resolver) {
            super(DOWNLOADS_PATH, NOTIFY_EVENTS);
            mResolver = resolver;
        }

        @Override
        public void startWatching() {
            super.startWatching();
            if (DEBUG) Log.d(TAG, "Started watching for file changes in: " + DOWNLOADS_PATH);
        }

        @Override
        public void stopWatching() {
            super.stopWatching();
            if (DEBUG) Log.d(TAG, "Stopped watching for file changes in: " + DOWNLOADS_PATH);
        }

        @Override
        public void onEvent(int event, String path) {
            if ((event & NOTIFY_EVENTS) != 0) {
                if (DEBUG) Log.v(TAG, "Change detected at path: " + DOWNLOADS_PATH);
                mResolver.notifyChange(Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI, null, false);
                mResolver.notifyChange(Downloads.Impl.CONTENT_URI, null, false);
            }
        }
    }
}
