/*
 * Copyright (C) 2015 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.documentsui;

import android.content.ContentResolver;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.ProviderInfo;
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.*;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
import android.provider.DocumentsContract.Root;
import android.provider.DocumentsProvider;
import androidx.annotation.VisibleForTesting;
import android.text.TextUtils;
import android.util.Log;

import android.os.FileUtils;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CountDownLatch;

public class StubProvider extends DocumentsProvider {

    public static final String DEFAULT_AUTHORITY = "com.android.documentsui.stubprovider";
    public static final String ROOT_0_ID = "TEST_ROOT_0";
    public static final String ROOT_1_ID = "TEST_ROOT_1";

    public static final String EXTRA_SIZE = "com.android.documentsui.stubprovider.SIZE";
    public static final String EXTRA_ROOT = "com.android.documentsui.stubprovider.ROOT";
    public static final String EXTRA_PATH = "com.android.documentsui.stubprovider.PATH";
    public static final String EXTRA_STREAM_TYPES
            = "com.android.documentsui.stubprovider.STREAM_TYPES";
    public static final String EXTRA_CONTENT = "com.android.documentsui.stubprovider.CONTENT";
    public static final String EXTRA_ENABLE_ROOT_NOTIFICATION
            = "com.android.documentsui.stubprovider.ROOT_NOTIFICATION";

    public static final String EXTRA_FLAGS = "com.android.documentsui.stubprovider.FLAGS";
    public static final String EXTRA_PARENT_ID = "com.android.documentsui.stubprovider.PARENT";

    private static final String TAG = "StubProvider";

    private static final String STORAGE_SIZE_KEY = "documentsui.stubprovider.size";
    private static int DEFAULT_ROOT_SIZE = 1024 * 1024 * 500; // 500 MB.

    private static final String[] DEFAULT_ROOT_PROJECTION = new String[] {
            Root.COLUMN_ROOT_ID, Root.COLUMN_FLAGS, Root.COLUMN_TITLE, Root.COLUMN_DOCUMENT_ID,
            Root.COLUMN_AVAILABLE_BYTES
    };
    private static final String[] DEFAULT_DOCUMENT_PROJECTION = new String[] {
            Document.COLUMN_DOCUMENT_ID, Document.COLUMN_MIME_TYPE, Document.COLUMN_DISPLAY_NAME,
            Document.COLUMN_LAST_MODIFIED, Document.COLUMN_FLAGS, Document.COLUMN_SIZE,
    };

    private final Map<String, StubDocument> mStorage = new HashMap<>();
    private final Map<String, RootInfo> mRoots = new HashMap<>();
    private final Object mWriteLock = new Object();

    private String mAuthority = DEFAULT_AUTHORITY;
    private SharedPreferences mPrefs;
    private Set<String> mSimulateReadErrorIds = new HashSet<>();
    private long mLoadingDuration = 0;
    private boolean mRootNotification = true;

    @Override
    public void attachInfo(Context context, ProviderInfo info) {
        mAuthority = info.authority;
        super.attachInfo(context, info);
    }

    @Override
    public boolean onCreate() {
        clearCacheAndBuildRoots();
        return true;
    }

    @VisibleForTesting
    public void clearCacheAndBuildRoots() {
        Log.d(TAG, "Resetting storage.");
        removeChildrenRecursively(getContext().getCacheDir());
        mStorage.clear();
        mSimulateReadErrorIds.clear();

        mPrefs = getContext().getSharedPreferences(
                "com.android.documentsui.stubprovider.preferences", Context.MODE_PRIVATE);
        Collection<String> rootIds = mPrefs.getStringSet("roots", null);
        if (rootIds == null) {
            rootIds = Arrays.asList(new String[] { ROOT_0_ID, ROOT_1_ID });
        }

        mRoots.clear();
        for (String rootId : rootIds) {
            // Make a subdir in the cache dir for each root.
            final File file = new File(getContext().getCacheDir(), rootId);
            if (file.mkdir()) {
                Log.i(TAG, "Created new root directory @ " + file.getPath());
            }
            final RootInfo rootInfo = new RootInfo(file, getSize(rootId));

            if(rootId.equals(ROOT_1_ID)) {
                rootInfo.setSearchEnabled(false);
            }

            mStorage.put(rootInfo.document.documentId, rootInfo.document);
            mRoots.put(rootId, rootInfo);
        }

        mLoadingDuration = 0;
    }

    /**
     * @return Storage size, in bytes.
     */
    private long getSize(String rootId) {
        final String key = STORAGE_SIZE_KEY + "." + rootId;
        return mPrefs.getLong(key, DEFAULT_ROOT_SIZE);
    }

    @Override
    public Cursor queryRoots(String[] projection) throws FileNotFoundException {
        final MatrixCursor result = new MatrixCursor(projection != null ? projection
                : DEFAULT_ROOT_PROJECTION);
        for (Map.Entry<String, RootInfo> entry : mRoots.entrySet()) {
            final String id = entry.getKey();
            final RootInfo info = entry.getValue();
            final RowBuilder row = result.newRow();
            row.add(Root.COLUMN_ROOT_ID, id);
            row.add(Root.COLUMN_FLAGS, info.flags);
            row.add(Root.COLUMN_TITLE, id);
            row.add(Root.COLUMN_DOCUMENT_ID, info.document.documentId);
            row.add(Root.COLUMN_AVAILABLE_BYTES, info.getRemainingCapacity());
        }
        return result;
    }

    @Override
    public Cursor queryDocument(String documentId, String[] projection)
            throws FileNotFoundException {
        final MatrixCursor result = new MatrixCursor(projection != null ? projection
                : DEFAULT_DOCUMENT_PROJECTION);
        final StubDocument file = mStorage.get(documentId);
        if (file == null) {
            throw new FileNotFoundException();
        }
        includeDocument(result, file);
        return result;
    }

    @Override
    public boolean isChildDocument(String parentDocId, String docId) {
        final StubDocument parentDocument = mStorage.get(parentDocId);
        final StubDocument childDocument = mStorage.get(docId);
        return FileUtils.contains(parentDocument.file, childDocument.file);
    }

    @Override
    public String createDocument(String parentId, String mimeType, String displayName)
            throws FileNotFoundException {
        StubDocument parent = mStorage.get(parentId);
        File file = createFile(parent, mimeType, displayName);

        final StubDocument document = StubDocument.createRegularDocument(file, mimeType, parent);
        mStorage.put(document.documentId, document);
        Log.d(TAG, "Created document " + document.documentId);
        notifyParentChanged(document.parentId);
        getContext().getContentResolver().notifyChange(
                DocumentsContract.buildDocumentUri(mAuthority, document.documentId),
                null, false);

        return document.documentId;
    }

    @Override
    public void deleteDocument(String documentId)
            throws FileNotFoundException {
        final StubDocument document = mStorage.get(documentId);
        final long fileSize = document.file.length();
        if (document == null || !document.file.delete())
            throw new FileNotFoundException();
        synchronized (mWriteLock) {
            document.rootInfo.size -= fileSize;
            mStorage.remove(documentId);
        }
        Log.d(TAG, "Document deleted: " + documentId);
        notifyParentChanged(document.parentId);
        getContext().getContentResolver().notifyChange(
                DocumentsContract.buildDocumentUri(mAuthority, document.documentId),
                null, false);
    }

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

    @Override
    public Cursor queryChildDocuments(String parentDocumentId, String[] projection, String sortOrder)
            throws FileNotFoundException {
        if (mLoadingDuration > 0) {
            final Uri notifyUri = DocumentsContract.buildDocumentUri(mAuthority, parentDocumentId);
            final ContentResolver resolver = getContext().getContentResolver();
            new Handler(Looper.getMainLooper()).postDelayed(
                    () -> resolver.notifyChange(notifyUri, null, false),
                    mLoadingDuration);
            mLoadingDuration = 0;

            MatrixCursor cursor = new MatrixCursor(projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION);
            Bundle bundle = new Bundle();
            bundle.putBoolean(DocumentsContract.EXTRA_LOADING, true);
            cursor.setExtras(bundle);
            cursor.setNotificationUri(resolver, notifyUri);
            return cursor;
        } else {
            final StubDocument parentDocument = mStorage.get(parentDocumentId);
            if (parentDocument == null || parentDocument.file.isFile()) {
                throw new FileNotFoundException();
            }
            final MatrixCursor result = new MatrixCursor(projection != null ? projection
                    : DEFAULT_DOCUMENT_PROJECTION);
            result.setNotificationUri(getContext().getContentResolver(),
                    DocumentsContract.buildChildDocumentsUri(mAuthority, parentDocumentId));
            StubDocument document;
            for (File file : parentDocument.file.listFiles()) {
                document = mStorage.get(getDocumentIdForFile(file));
                if (document != null) {
                    includeDocument(result, document);
                }
            }
            return result;
        }
    }

    @Override
    public Cursor queryRecentDocuments(String rootId, String[] projection)
            throws FileNotFoundException {
        final MatrixCursor result = new MatrixCursor(projection != null ? projection
                : DEFAULT_DOCUMENT_PROJECTION);
        return result;
    }

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

        StubDocument parentDocument = mRoots.get(rootId).document;
        if (parentDocument == null || parentDocument.file.isFile()) {
            throw new FileNotFoundException();
        }

        final MatrixCursor result = new MatrixCursor(
                projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION);

        for (File file : parentDocument.file.listFiles()) {
            if (file.getName().toLowerCase().contains(query)) {
                StubDocument document = mStorage.get(getDocumentIdForFile(file));
                if (document != null) {
                    includeDocument(result, document);
                }
            }
        }
        return result;
    }

    @Override
    public String renameDocument(String documentId, String displayName)
            throws FileNotFoundException {

        StubDocument oldDoc = mStorage.get(documentId);

        File before = oldDoc.file;
        File after = new File(before.getParentFile(), displayName);

        if (after.exists()) {
            throw new IllegalStateException("Already exists " + after);
        }

        boolean result = before.renameTo(after);

        if (!result) {
            throw new IllegalStateException("Failed to rename to " + after);
        }

        StubDocument newDoc = StubDocument.createRegularDocument(after, oldDoc.mimeType,
                mStorage.get(oldDoc.parentId));

        mStorage.remove(documentId);
        notifyParentChanged(oldDoc.parentId);
        getContext().getContentResolver().notifyChange(
                DocumentsContract.buildDocumentUri(mAuthority, oldDoc.documentId), null, false);

        mStorage.put(newDoc.documentId, newDoc);
        notifyParentChanged(newDoc.parentId);
        getContext().getContentResolver().notifyChange(
                DocumentsContract.buildDocumentUri(mAuthority, newDoc.documentId), null, false);

        if (!TextUtils.equals(documentId, newDoc.documentId)) {
            return newDoc.documentId;
        } else {
            return null;
        }
    }

    @Override
    public ParcelFileDescriptor openDocument(String docId, String mode, CancellationSignal signal)
            throws FileNotFoundException {

        final StubDocument document = mStorage.get(docId);
        if (document == null || !document.file.isFile()) {
            throw new FileNotFoundException();
        }
        if ((document.flags & Document.FLAG_VIRTUAL_DOCUMENT) != 0) {
            throw new IllegalStateException("Tried to open a virtual file.");
        }

        if ("r".equals(mode)) {
            if (mSimulateReadErrorIds.contains(docId)) {
                Log.d(TAG, "Simulated errs enabled. Open in the wrong mode.");
                return ParcelFileDescriptor.open(
                        document.file, ParcelFileDescriptor.MODE_WRITE_ONLY);
            }
            return ParcelFileDescriptor.open(document.file, ParcelFileDescriptor.MODE_READ_ONLY);
        }
        if ("w".equals(mode)) {
            return startWrite(document);
        }
        if ("wa".equals(mode)) {
            return startWrite(document, true);
        }


        throw new FileNotFoundException();
    }

    @VisibleForTesting
    public void simulateReadErrorsForFile(Uri uri) {
        simulateReadErrorsForFile(DocumentsContract.getDocumentId(uri));
    }

    public void simulateReadErrorsForFile(String id) {
        mSimulateReadErrorIds.add(id);
    }

    @Override
    public AssetFileDescriptor openDocumentThumbnail(
            String docId, Point sizeHint, CancellationSignal signal) throws FileNotFoundException {
        throw new FileNotFoundException();
    }

    @Override
    public AssetFileDescriptor openTypedDocument(
            String docId, String mimeTypeFilter, Bundle opts, CancellationSignal signal)
            throws FileNotFoundException {
        final StubDocument document = mStorage.get(docId);
        if (document == null || !document.file.isFile() || document.streamTypes == null) {
            throw new FileNotFoundException();
        }
        for (final String mimeType : document.streamTypes) {
            // Strict compare won't accept wildcards, but that's OK for tests, as DocumentsUI
            // doesn't use them for getStreamTypes nor openTypedDocument.
            if (mimeType.equals(mimeTypeFilter)) {
                ParcelFileDescriptor pfd = ParcelFileDescriptor.open(
                            document.file, ParcelFileDescriptor.MODE_READ_ONLY);
                if (mSimulateReadErrorIds.contains(docId)) {
                    pfd = new ParcelFileDescriptor(pfd) {
                        @Override
                        public void checkError() throws IOException {
                            throw new IOException("Test error");
                        }
                    };
                }
                return new AssetFileDescriptor(pfd, 0, document.file.length());
            }
        }
        throw new IllegalArgumentException("Invalid MIME type filter for openTypedDocument().");
    }

    @Override
    public String[] getStreamTypes(Uri uri, String mimeTypeFilter) {
        final StubDocument document = mStorage.get(DocumentsContract.getDocumentId(uri));
        if (document == null) {
            throw new IllegalArgumentException(
                    "The provided Uri is incorrect, or the file is gone.");
        }
        if (!"*/*".equals(mimeTypeFilter)) {
            // Not used by DocumentsUI, so don't bother implementing it.
            throw new UnsupportedOperationException();
        }
        if (document.streamTypes == null) {
            return null;
        }
        return document.streamTypes.toArray(new String[document.streamTypes.size()]);
    }

    private ParcelFileDescriptor startWrite(final StubDocument document)
            throws FileNotFoundException {
        return startWrite(document, false);
    }

    private ParcelFileDescriptor startWrite(final StubDocument document, boolean append)
            throws FileNotFoundException {
        ParcelFileDescriptor[] pipe;
        try {
            pipe = ParcelFileDescriptor.createReliablePipe();
        } catch (IOException exception) {
            throw new FileNotFoundException();
        }
        final ParcelFileDescriptor readPipe = pipe[0];
        final ParcelFileDescriptor writePipe = pipe[1];

        postToMainThread(() -> {
            InputStream inputStream = null;
            OutputStream outputStream = null;
            try {
                Log.d(TAG, "Opening write stream on file " + document.documentId);
                inputStream = new ParcelFileDescriptor.AutoCloseInputStream(readPipe);
                outputStream = new FileOutputStream(document.file, append);
                byte[] buffer = new byte[32 * 1024];
                int bytesToRead;
                int bytesRead = 0;
                while (bytesRead != -1) {
                    synchronized (mWriteLock) {
                        // This cast is safe because the max possible value is buffer.length.
                        bytesToRead = (int) Math.min(document.rootInfo.getRemainingCapacity(),
                                buffer.length);
                        if (bytesToRead == 0) {
                            closePipeWithErrorSilently(readPipe, "Not enough space.");
                            break;
                        }
                        bytesRead = inputStream.read(buffer, 0, bytesToRead);
                        if (bytesRead == -1) {
                            break;
                        }
                        outputStream.write(buffer, 0, bytesRead);
                        document.rootInfo.size += bytesRead;
                    }
                }
            } catch (IOException e) {
                Log.e(TAG, "Error on close", e);
                closePipeWithErrorSilently(readPipe, e.getMessage());
            } finally {
                FileUtils.closeQuietly(inputStream);
                FileUtils.closeQuietly(outputStream);
                Log.d(TAG, "Closing write stream on file " + document.documentId);
                notifyParentChanged(document.parentId);
                getContext().getContentResolver().notifyChange(
                        DocumentsContract.buildDocumentUri(mAuthority, document.documentId),
                        null, false);
            }
        });

        return writePipe;
    }

    private void closePipeWithErrorSilently(ParcelFileDescriptor pipe, String error) {
        try {
            pipe.closeWithError(error);
        } catch (IOException ignore) {
        }
    }

    @Override
    public Bundle call(String method, String arg, Bundle extras) {
        // We're not supposed to override any of the default DocumentsProvider
        // methods that are supported by "call", so javadoc asks that we
        // always call super.call first and return if response is not null.
        Bundle result = super.call(method, arg, extras);
        if (result != null) {
            return result;
        }

        switch (method) {
            case "clear":
                clearCacheAndBuildRoots();
                return null;
            case "configure":
                configure(arg, extras);
                return null;
            case "createVirtualFile":
                return createVirtualFileFromBundle(extras);
            case "simulateReadErrorsForFile":
                simulateReadErrorsForFile(arg);
                return null;
            case "createDocumentWithFlags":
                return dispatchCreateDocumentWithFlags(extras);
            case "setLoadingDuration":
                mLoadingDuration = extras.getLong(DocumentsContract.EXTRA_LOADING);
                return null;
            case "waitForWrite":
                waitForWrite();
                return null;
        }

        return null;
    }

    private Bundle createVirtualFileFromBundle(Bundle extras) {
        try {
            Uri uri = createVirtualFile(
                    extras.getString(EXTRA_ROOT),
                    extras.getString(EXTRA_PATH),
                    extras.getString(Document.COLUMN_MIME_TYPE),
                    extras.getStringArrayList(EXTRA_STREAM_TYPES),
                    extras.getByteArray(EXTRA_CONTENT));

            String documentId = DocumentsContract.getDocumentId(uri);
            Bundle result = new Bundle();
            result.putString(Document.COLUMN_DOCUMENT_ID, documentId);
            return result;
        } catch (IOException e) {
            Log.e(TAG, "Couldn't create virtual file.");
        }

        return null;
    }

    private Bundle dispatchCreateDocumentWithFlags(Bundle extras) {
        String rootId = extras.getString(EXTRA_PARENT_ID);
        String mimeType = extras.getString(Document.COLUMN_MIME_TYPE);
        String name = extras.getString(Document.COLUMN_DISPLAY_NAME);
        List<String> streamTypes = extras.getStringArrayList(EXTRA_STREAM_TYPES);
        int flags = extras.getInt(EXTRA_FLAGS);

        Bundle out = new Bundle();
        String documentId = null;
        try {
            documentId = createDocument(rootId, mimeType, name, flags, streamTypes);
            Uri uri = DocumentsContract.buildDocumentUri(mAuthority, documentId);
            out.putParcelable(DocumentsContract.EXTRA_URI, uri);
        } catch (FileNotFoundException e) {
            Log.d(TAG, "Creating document with flags failed" + name);
        }
        return out;
    }

    private void waitForWrite() {
        try {
            CountDownLatch latch = new CountDownLatch(1);
            postToMainThread(latch::countDown);
            latch.await();
            Log.d(TAG, "All writing is done.");
        } catch (InterruptedException e) {
            // should never happen
            throw new RuntimeException(e);
        }
    }

    private void postToMainThread(Runnable r) {
        new Handler(Looper.getMainLooper()).post(r);
    }

    public String createDocument(String parentId, String mimeType, String displayName, int flags,
            List<String> streamTypes) throws FileNotFoundException {

        StubDocument parent = mStorage.get(parentId);
        File file = createFile(parent, mimeType, displayName);

        final StubDocument document = StubDocument.createDocumentWithFlags(file, mimeType, parent,
                flags, streamTypes);
        mStorage.put(document.documentId, document);
        Log.d(TAG, "Created document " + document.documentId);
        notifyParentChanged(document.parentId);
        getContext().getContentResolver().notifyChange(
                DocumentsContract.buildDocumentUri(mAuthority, document.documentId),
                null, false);

        return document.documentId;
    }

    private File createFile(StubDocument parent, String mimeType, String displayName)
            throws FileNotFoundException {
        if (parent == null) {
            throw new IllegalArgumentException(
                    "Can't create file " + displayName + " in null parent.");
        }
        if (!parent.file.isDirectory()) {
            throw new IllegalArgumentException(
                    "Can't create file " + displayName + " inside non-directory parent "
                            + parent.file.getName());
        }

        final File file = new File(parent.file, displayName);
        if (file.exists()) {
            throw new FileNotFoundException(
                    "Duplicate file names not supported for " + file);
        }

        if (mimeType.equals(Document.MIME_TYPE_DIR)) {
            if (!file.mkdirs()) {
                throw new FileNotFoundException("Failed to create directory(s): " + file);
            }
            Log.i(TAG, "Created new directory: " + file);
        } else {
            boolean created = false;
            try {
                created = file.createNewFile();
            } catch (IOException e) {
                // We'll throw an FNF exception later :)
                Log.e(TAG, "createNewFile operation failed for file: " + file, e);
            }
            if (!created) {
                throw new FileNotFoundException("createNewFile operation failed for: " + file);
            }
            Log.i(TAG, "Created new file: " + file);
        }
        return file;
    }

    private void configure(String arg, Bundle extras) {
        Log.d(TAG, "Configure " + arg);
        String rootName = extras.getString(EXTRA_ROOT, ROOT_0_ID);
        long rootSize = extras.getLong(EXTRA_SIZE, 100) * 1024 * 1024;
        setSize(rootName, rootSize);
        mRootNotification = extras.getBoolean(EXTRA_ENABLE_ROOT_NOTIFICATION, true);
    }

    private void notifyParentChanged(String parentId) {
        getContext().getContentResolver().notifyChange(
                DocumentsContract.buildChildDocumentsUri(mAuthority, parentId), null, false);
        if (mRootNotification) {
            // Notify also about possible change in remaining space on the root.
            getContext().getContentResolver().notifyChange(
                    DocumentsContract.buildRootsUri(mAuthority), null, false);
        }
    }

    private void includeDocument(MatrixCursor result, StubDocument document) {
        final RowBuilder row = result.newRow();
        row.add(Document.COLUMN_DOCUMENT_ID, document.documentId);
        row.add(Document.COLUMN_DISPLAY_NAME, document.file.getName());
        row.add(Document.COLUMN_SIZE, document.file.length());
        row.add(Document.COLUMN_MIME_TYPE, document.mimeType);
        row.add(Document.COLUMN_FLAGS, document.flags);
        row.add(Document.COLUMN_LAST_MODIFIED, document.file.lastModified());
    }

    private void removeChildrenRecursively(File file) {
        for (File childFile : file.listFiles()) {
            if (childFile.isDirectory()) {
                removeChildrenRecursively(childFile);
            }
            childFile.delete();
        }
    }

    public void setSize(String rootId, long rootSize) {
        RootInfo root = mRoots.get(rootId);
        if (root != null) {
            final String key = STORAGE_SIZE_KEY + "." + rootId;
            Log.d(TAG, "Set size of " + key + " : " + rootSize);

            // Persist the size.
            SharedPreferences.Editor editor = mPrefs.edit();
            editor.putLong(key, rootSize);
            editor.apply();
            // Apply the size in the current instance of this provider.
            root.capacity = rootSize;
            getContext().getContentResolver().notifyChange(
                    DocumentsContract.buildRootsUri(mAuthority),
                    null, false);
        } else {
            Log.e(TAG, "Attempt to configure non-existent root: " + rootId);
        }
    }

    @VisibleForTesting
    public Uri createRegularFile(String rootId, String path, String mimeType, byte[] content)
            throws FileNotFoundException, IOException {
        final File file = createFile(rootId, path, mimeType, content);
        final StubDocument parent = mStorage.get(getDocumentIdForFile(file.getParentFile()));
        if (parent == null) {
            throw new FileNotFoundException("Parent not found.");
        }
        final StubDocument document = StubDocument.createRegularDocument(file, mimeType, parent);
        mStorage.put(document.documentId, document);
        return DocumentsContract.buildDocumentUri(mAuthority, document.documentId);
    }

    @VisibleForTesting
    public Uri createVirtualFile(
            String rootId, String path, String mimeType, List<String> streamTypes, byte[] content)
            throws FileNotFoundException, IOException {

        final File file = createFile(rootId, path, mimeType, content);
        final StubDocument parent = mStorage.get(getDocumentIdForFile(file.getParentFile()));
        if (parent == null) {
            throw new FileNotFoundException("Parent not found.");
        }
        final StubDocument document = StubDocument.createVirtualDocument(
                file, mimeType, streamTypes, parent);
        mStorage.put(document.documentId, document);
        return DocumentsContract.buildDocumentUri(mAuthority, document.documentId);
    }

    @VisibleForTesting
    public File getFile(String rootId, String path) throws FileNotFoundException {
        StubDocument root = mRoots.get(rootId).document;
        if (root == null) {
            throw new FileNotFoundException("No roots with the ID " + rootId + " were found");
        }
        // Convert the path string into a path that's relative to the root.
        File needle = new File(root.file, path.substring(1));

        StubDocument found = mStorage.get(getDocumentIdForFile(needle));
        if (found == null) {
            return null;
        }
        return found.file;
    }

    private File createFile(String rootId, String path, String mimeType, byte[] content)
            throws FileNotFoundException, IOException {
        Log.d(TAG, "Creating test file " + rootId + " : " + path);
        StubDocument root = mRoots.get(rootId).document;
        if (root == null) {
            throw new FileNotFoundException("No roots with the ID " + rootId + " were found");
        }
        final File file = new File(root.file, path.substring(1));
        if (DocumentsContract.Document.MIME_TYPE_DIR.equals(mimeType)) {
            if (!file.mkdirs()) {
                throw new FileNotFoundException("Couldn't create directory " + file.getPath());
            }
        } else {
            if (!file.createNewFile()) {
                throw new FileNotFoundException("Couldn't create file " + file.getPath());
            }
            try (final FileOutputStream fout = new FileOutputStream(file)) {
                fout.write(content);
            }
        }
        return file;
    }

    final static class RootInfo {
        private static final int DEFAULT_ROOTS_FLAGS = Root.FLAG_SUPPORTS_SEARCH
                | Root.FLAG_SUPPORTS_CREATE | Root.FLAG_SUPPORTS_IS_CHILD;

        public final String name;
        public final StubDocument document;
        public long capacity;
        public long size;
        public int flags;

        RootInfo(File file, long capacity) {
            this.name = file.getName();
            this.capacity = 1024 * 1024;
            this.flags = DEFAULT_ROOTS_FLAGS;
            this.capacity = capacity;
            this.size = 0;
            this.document = StubDocument.createRootDocument(file, this);
        }

        public long getRemainingCapacity() {
            return capacity - size;
        }

        public void setSearchEnabled(boolean enabled) {
            flags = enabled ? (flags | Root.FLAG_SUPPORTS_SEARCH)
                    : (flags & ~Root.FLAG_SUPPORTS_SEARCH);
        }

    }

    final static class StubDocument {
        public final File file;
        public final String documentId;
        public final String mimeType;
        public final List<String> streamTypes;
        public final int flags;
        public final String parentId;
        public final RootInfo rootInfo;

        private StubDocument(File file, String mimeType, List<String> streamTypes, int flags,
                StubDocument parent) {
            this.file = file;
            this.documentId = getDocumentIdForFile(file);
            this.mimeType = mimeType;
            this.streamTypes = streamTypes;
            this.flags = flags;
            this.parentId = parent.documentId;
            this.rootInfo = parent.rootInfo;
        }

        private StubDocument(File file, RootInfo rootInfo) {
            this.file = file;
            this.documentId = getDocumentIdForFile(file);
            this.mimeType = Document.MIME_TYPE_DIR;
            this.streamTypes = new ArrayList<>();
            this.flags = Document.FLAG_DIR_SUPPORTS_CREATE | Document.FLAG_SUPPORTS_RENAME;
            this.parentId = null;
            this.rootInfo = rootInfo;
        }

        public static StubDocument createRootDocument(File file, RootInfo rootInfo) {
            return new StubDocument(file, rootInfo);
        }

        public static StubDocument createRegularDocument(
                File file, String mimeType, StubDocument parent) {
            int flags = Document.FLAG_SUPPORTS_DELETE | Document.FLAG_SUPPORTS_RENAME;
            if (file.isDirectory()) {
                flags |= Document.FLAG_DIR_SUPPORTS_CREATE;
            } else {
                flags |= Document.FLAG_SUPPORTS_WRITE;
            }
            return new StubDocument(file, mimeType, new ArrayList<String>(), flags, parent);
        }

        public static StubDocument createDocumentWithFlags(
                File file, String mimeType, StubDocument parent, int flags,
                List<String> streamTypes) {
            return new StubDocument(file, mimeType, streamTypes, flags, parent);
        }

        public static StubDocument createVirtualDocument(
                File file, String mimeType, List<String> streamTypes, StubDocument parent) {
            int flags = Document.FLAG_SUPPORTS_DELETE | Document.FLAG_SUPPORTS_WRITE
                    | Document.FLAG_VIRTUAL_DOCUMENT;
            return new StubDocument(file, mimeType, streamTypes, flags, parent);
        }

        @Override
        public String toString() {
            return "StubDocument{"
                    + "path:" + file.getPath()
                    + ", documentId:" + documentId
                    + ", mimeType:" + mimeType
                    + ", streamTypes:" + streamTypes.toString()
                    + ", flags:" + flags
                    + ", parentId:" + parentId
                    + ", rootInfo:" + rootInfo
                    + "}";
        }
    }

    private static String getDocumentIdForFile(File file) {
        return file.getAbsolutePath();
    }
}
