/*
 * 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.mtp;

import static com.android.mtp.MtpDatabaseConstants.*;

import android.annotation.Nullable;
import android.content.ContentValues;
import android.content.Context;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.MatrixCursor;
import android.database.MatrixCursor.RowBuilder;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.media.MediaFile;
import android.mtp.MtpConstants;
import android.mtp.MtpObjectInfo;
import android.net.Uri;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
import android.provider.DocumentsContract.Root;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;

import java.io.FileNotFoundException;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

/**
 * Database for MTP objects.
 * The object handle which is identifier for object in MTP protocol is not stable over sessions.
 * When we resume the process, we need to remap our document ID with MTP's object handle.
 *
 * If the remote MTP device is backed by typical file system, the file name
 * is unique among files in a directory. However, MTP protocol itself does
 * not guarantee the uniqueness of name so we cannot use fullpath as ID.
 *
 * Instead of fullpath, we use artificial ID generated by MtpDatabase itself. The database object
 * remembers the map of document ID and object handle, and remaps new object handle with document ID
 * by comparing the directory structure and object name.
 *
 * To start putting documents into the database, the client needs to call
 * {@link Mapper#startAddingDocuments(String)} with the parent document ID. Also it
 * needs to call {@link Mapper#stopAddingDocuments(String)} after putting all child
 * documents to the database. (All explanations are same for root documents)
 *
 * database.getMapper().startAddingDocuments();
 * database.getMapper().putChildDocuments();
 * database.getMapper().stopAddingDocuments();
 *
 * To update the existing documents, the client code can repeat to call the three methods again.
 * The newly added rows update corresponding existing rows that have same MTP identifier like
 * objectHandle.
 *
 * The client can call putChildDocuments multiple times to add documents by chunk, but it needs to
 * put all documents under the parent before calling stopAddingChildDocuments. Otherwise missing
 * documents are regarded as deleted, and will be removed from the database.
 *
 * If the client calls clearMtpIdentifier(), it clears MTP identifier in the database. In this case,
 * the database tries to find corresponding rows by using document's name instead of MTP identifier
 * at the next update cycle.
 *
 * TODO: Improve performance by SQL optimization.
 */
class MtpDatabase {
    private final SQLiteDatabase mDatabase;
    private final Mapper mMapper;

    SQLiteDatabase getSQLiteDatabase() {
        return mDatabase;
    }

    MtpDatabase(Context context, int flags) {
        final OpenHelper helper = new OpenHelper(context, flags);
        mDatabase = helper.getWritableDatabase();
        mMapper = new Mapper(this);
    }

    void close() {
        mDatabase.close();
    }

    /**
     * Returns operations for mapping.
     * @return Mapping operations.
     */
    Mapper getMapper() {
        return mMapper;
    }

    /**
     * Queries roots information.
     * @param columnNames Column names defined in {@link android.provider.DocumentsContract.Root}.
     * @return Database cursor.
     */
    Cursor queryRoots(Resources resources, String[] columnNames) {
        final String selection =
                COLUMN_ROW_STATE + " IN (?, ?) AND " + COLUMN_DOCUMENT_TYPE + " = ?";
        final Cursor deviceCursor = mDatabase.query(
                TABLE_DOCUMENTS,
                strings(COLUMN_DEVICE_ID),
                selection,
                strings(ROW_STATE_VALID, ROW_STATE_INVALIDATED, DOCUMENT_TYPE_DEVICE),
                COLUMN_DEVICE_ID,
                null,
                null,
                null);

        try {
            final SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
            builder.setTables(JOIN_ROOTS);
            builder.setProjectionMap(COLUMN_MAP_ROOTS);
            final MatrixCursor result = new MatrixCursor(columnNames);
            final ContentValues values = new ContentValues();

            while (deviceCursor.moveToNext()) {
                final int deviceId = deviceCursor.getInt(0);
                final Cursor storageCursor = builder.query(
                        mDatabase,
                        columnNames,
                        selection + " AND " + COLUMN_DEVICE_ID + " = ?",
                        strings(ROW_STATE_VALID,
                                ROW_STATE_INVALIDATED,
                                DOCUMENT_TYPE_STORAGE,
                                deviceId),
                        null,
                        null,
                        null);
                try {
                    values.clear();
                    try (final Cursor deviceRoot = builder.query(
                            mDatabase,
                            columnNames,
                            selection + " AND " + COLUMN_DEVICE_ID + " = ?",
                            strings(ROW_STATE_VALID,
                                    ROW_STATE_INVALIDATED,
                                    DOCUMENT_TYPE_DEVICE,
                                    deviceId),
                            null,
                            null,
                            null)) {
                        deviceRoot.moveToNext();
                        DatabaseUtils.cursorRowToContentValues(deviceRoot, values);
                    }

                    if (storageCursor.getCount() != 0) {
                        long capacityBytes = 0;
                        long availableBytes = 0;
                        final int capacityIndex =
                                storageCursor.getColumnIndex(Root.COLUMN_CAPACITY_BYTES);
                        final int availableIndex =
                                storageCursor.getColumnIndex(Root.COLUMN_AVAILABLE_BYTES);
                        while (storageCursor.moveToNext()) {
                            // If requested columnNames does not include COLUMN_XXX_BYTES, we
                            // don't calculate corresponding values.
                            if (capacityIndex != -1) {
                                capacityBytes += storageCursor.getLong(capacityIndex);
                            }
                            if (availableIndex != -1) {
                                availableBytes += storageCursor.getLong(availableIndex);
                            }
                        }
                        values.put(Root.COLUMN_CAPACITY_BYTES, capacityBytes);
                        values.put(Root.COLUMN_AVAILABLE_BYTES, availableBytes);
                    } else {
                        values.putNull(Root.COLUMN_CAPACITY_BYTES);
                        values.putNull(Root.COLUMN_AVAILABLE_BYTES);
                    }
                    if (storageCursor.getCount() == 1 && values.containsKey(Root.COLUMN_TITLE)) {
                        storageCursor.moveToFirst();
                        // Add storage name to device name if we have only 1 storage.
                        values.put(
                                Root.COLUMN_TITLE,
                                resources.getString(
                                        R.string.root_name,
                                        values.getAsString(Root.COLUMN_TITLE),
                                        storageCursor.getString(
                                                storageCursor.getColumnIndex(Root.COLUMN_TITLE))));
                    }
                } finally {
                    storageCursor.close();
                }

                final RowBuilder row = result.newRow();
                for (final String key : values.keySet()) {
                    row.add(key, values.get(key));
                }
            }

            return result;
        } finally {
            deviceCursor.close();
        }
    }

    /**
     * Queries root documents information.
     * @param columnNames Column names defined in
     *     {@link android.provider.DocumentsContract.Document}.
     * @return Database cursor.
     */
    @VisibleForTesting
    Cursor queryRootDocuments(String[] columnNames) {
        return mDatabase.query(
                TABLE_DOCUMENTS,
                columnNames,
                COLUMN_ROW_STATE + " IN (?, ?) AND " + COLUMN_DOCUMENT_TYPE + " = ?",
                strings(ROW_STATE_VALID, ROW_STATE_INVALIDATED, DOCUMENT_TYPE_STORAGE),
                null,
                null,
                null);
    }

    /**
     * Queries documents information.
     * @param columnNames Column names defined in
     *     {@link android.provider.DocumentsContract.Document}.
     * @return Database cursor.
     */
    Cursor queryChildDocuments(String[] columnNames, String parentDocumentId) {
        return mDatabase.query(
                TABLE_DOCUMENTS,
                columnNames,
                COLUMN_ROW_STATE + " IN (?, ?) AND " + COLUMN_PARENT_DOCUMENT_ID + " = ?",
                strings(ROW_STATE_VALID, ROW_STATE_INVALIDATED, parentDocumentId),
                null,
                null,
                null);
    }

    /**
     * Returns document IDs of storages under the given device document.
     *
     * @param documentId Document ID that points a device.
     * @return Storage document IDs.
     * @throws FileNotFoundException The given document ID is not registered in database.
     */
    String[] getStorageDocumentIds(String documentId)
            throws FileNotFoundException {
        Preconditions.checkArgument(createIdentifier(documentId).mDocumentType ==
                DOCUMENT_TYPE_DEVICE);
        // Check if the parent document is device that has single storage.
        try (final Cursor cursor = mDatabase.query(
                TABLE_DOCUMENTS,
                strings(Document.COLUMN_DOCUMENT_ID),
                COLUMN_ROW_STATE + " IN (?, ?) AND " +
                COLUMN_PARENT_DOCUMENT_ID + " = ? AND " +
                COLUMN_DOCUMENT_TYPE + " = ?",
                strings(ROW_STATE_VALID,
                        ROW_STATE_INVALIDATED,
                        documentId,
                        DOCUMENT_TYPE_STORAGE),
                null,
                null,
                null)) {
            final String[] ids = new String[cursor.getCount()];
            for (int i = 0; cursor.moveToNext(); i++) {
                ids[i] = cursor.getString(0);
            }
            return ids;
        }
    }

    /**
     * Queries a single document.
     * @param documentId
     * @param projection
     * @return Database cursor.
     */
    Cursor queryDocument(String documentId, String[] projection) {
        return mDatabase.query(
                TABLE_DOCUMENTS,
                projection,
                SELECTION_DOCUMENT_ID,
                strings(documentId),
                null,
                null,
                null,
                "1");
    }

    @Nullable String getDocumentIdForDevice(int deviceId) {
        final Cursor cursor = mDatabase.query(
                TABLE_DOCUMENTS,
                strings(Document.COLUMN_DOCUMENT_ID),
                COLUMN_DOCUMENT_TYPE + " = ? AND " + COLUMN_DEVICE_ID + " = ?",
                strings(DOCUMENT_TYPE_DEVICE, deviceId),
                null,
                null,
                null,
                "1");
        try {
            if (cursor.moveToNext()) {
                return cursor.getString(0);
            } else {
                return null;
            }
        } finally {
            cursor.close();
        }
    }

    /**
     * Obtains parent identifier.
     * @param documentId
     * @return parent identifier.
     * @throws FileNotFoundException
     */
    Identifier getParentIdentifier(String documentId) throws FileNotFoundException {
        final Cursor cursor = mDatabase.query(
                TABLE_DOCUMENTS,
                strings(COLUMN_PARENT_DOCUMENT_ID),
                SELECTION_DOCUMENT_ID,
                strings(documentId),
                null,
                null,
                null,
                "1");
        try {
            if (cursor.moveToNext()) {
                return createIdentifier(cursor.getString(0));
            } else {
                throw new FileNotFoundException("Cannot find a row having ID = " + documentId);
            }
        } finally {
            cursor.close();
        }
    }

    String getDeviceDocumentId(int deviceId) throws FileNotFoundException {
        try (final Cursor cursor = mDatabase.query(
                TABLE_DOCUMENTS,
                strings(Document.COLUMN_DOCUMENT_ID),
                COLUMN_DEVICE_ID + " = ? AND " + COLUMN_DOCUMENT_TYPE + " = ? AND " +
                COLUMN_ROW_STATE + " != ?",
                strings(deviceId, DOCUMENT_TYPE_DEVICE, ROW_STATE_DISCONNECTED),
                null,
                null,
                null,
                "1")) {
            if (cursor.getCount() > 0) {
                cursor.moveToNext();
                return cursor.getString(0);
            } else {
                throw new FileNotFoundException("The device ID not found: " + deviceId);
            }
        }
    }

    /**
     * Adds new document under the parent.
     * The method does not affect invalidated and pending documents because we know the document is
     * newly added and never mapped with existing ones.
     * @param parentDocumentId
     * @param info
     * @return Document ID of added document.
     */
    String putNewDocument(
            int deviceId, String parentDocumentId, int[] operationsSupported, MtpObjectInfo info) {
        final ContentValues values = new ContentValues();
        getObjectDocumentValues(values, deviceId, parentDocumentId, operationsSupported, info);
        mDatabase.beginTransaction();
        try {
            final long id = mDatabase.insert(TABLE_DOCUMENTS, null, values);
            mDatabase.setTransactionSuccessful();
            return Long.toString(id);
        } finally {
            mDatabase.endTransaction();
        }
    }

    /**
     * Deletes document and its children.
     * @param documentId
     */
    void deleteDocument(String documentId) {
        deleteDocumentsAndRootsRecursively(SELECTION_DOCUMENT_ID, strings(documentId));
    }

    /**
     * Gets identifier from document ID.
     * @param documentId Document ID.
     * @return Identifier.
     * @throws FileNotFoundException
     */
    Identifier createIdentifier(String documentId) throws FileNotFoundException {
        // Currently documentId is old format.
        final Cursor cursor = mDatabase.query(
                TABLE_DOCUMENTS,
                strings(COLUMN_DEVICE_ID,
                        COLUMN_STORAGE_ID,
                        COLUMN_OBJECT_HANDLE,
                        COLUMN_DOCUMENT_TYPE),
                SELECTION_DOCUMENT_ID + " AND " + COLUMN_ROW_STATE + " IN (?, ?)",
                strings(documentId, ROW_STATE_VALID, ROW_STATE_INVALIDATED),
                null,
                null,
                null,
                "1");
        try {
            if (cursor.getCount() == 0) {
                throw new FileNotFoundException("ID \"" + documentId + "\" is not found.");
            } else {
                cursor.moveToNext();
                return new Identifier(
                        cursor.getInt(0),
                        cursor.getInt(1),
                        cursor.getInt(2),
                        documentId,
                        cursor.getInt(3));
            }
        } finally {
            cursor.close();
        }
    }

    /**
     * Deletes a document, and its root information if the document is a root document.
     * @param selection Query to select documents.
     * @param args Arguments for selection.
     * @return Whether the method deletes rows.
     */
    boolean deleteDocumentsAndRootsRecursively(String selection, String[] args) {
        mDatabase.beginTransaction();
        try {
            boolean changed = false;
            final Cursor cursor = mDatabase.query(
                    TABLE_DOCUMENTS,
                    strings(Document.COLUMN_DOCUMENT_ID),
                    selection,
                    args,
                    null,
                    null,
                    null);
            try {
                while (cursor.moveToNext()) {
                    if (deleteDocumentsAndRootsRecursively(
                            COLUMN_PARENT_DOCUMENT_ID + " = ?",
                            strings(cursor.getString(0)))) {
                        changed = true;
                    }
                }
            } finally {
                cursor.close();
            }
            if (deleteDocumentsAndRoots(selection, args)) {
                changed = true;
            }
            mDatabase.setTransactionSuccessful();
            return changed;
        } finally {
            mDatabase.endTransaction();
        }
    }

    /**
     * Marks the documents and their child as disconnected documents.
     * @param selection
     * @param args
     * @return True if at least one row is updated.
     */
    boolean disconnectDocumentsRecursively(String selection, String[] args) {
        mDatabase.beginTransaction();
        try {
            boolean changed = false;
            try (final Cursor cursor = mDatabase.query(
                    TABLE_DOCUMENTS,
                    strings(Document.COLUMN_DOCUMENT_ID),
                    selection,
                    args,
                    null,
                    null,
                    null)) {
                while (cursor.moveToNext()) {
                    if (disconnectDocumentsRecursively(
                            COLUMN_PARENT_DOCUMENT_ID + " = ?",
                            strings(cursor.getString(0)))) {
                        changed = true;
                    }
                }
            }
            if (disconnectDocuments(selection, args)) {
                changed = true;
            }
            mDatabase.setTransactionSuccessful();
            return changed;
        } finally {
            mDatabase.endTransaction();
        }
    }

    boolean deleteDocumentsAndRoots(String selection, String[] args) {
        mDatabase.beginTransaction();
        try {
            int deleted = 0;
            deleted += mDatabase.delete(
                    TABLE_ROOT_EXTRA,
                    Root.COLUMN_ROOT_ID + " IN (" + SQLiteQueryBuilder.buildQueryString(
                            false,
                            TABLE_DOCUMENTS,
                            new String[] { Document.COLUMN_DOCUMENT_ID },
                            selection,
                            null,
                            null,
                            null,
                            null) + ")",
                    args);
            deleted += mDatabase.delete(TABLE_DOCUMENTS, selection, args);
            mDatabase.setTransactionSuccessful();
            // TODO Remove mappingState.
            return deleted != 0;
        } finally {
            mDatabase.endTransaction();
        }
    }

    boolean disconnectDocuments(String selection, String[] args) {
        mDatabase.beginTransaction();
        try {
            final ContentValues values = new ContentValues();
            values.put(COLUMN_ROW_STATE, ROW_STATE_DISCONNECTED);
            values.putNull(COLUMN_DEVICE_ID);
            values.putNull(COLUMN_STORAGE_ID);
            values.putNull(COLUMN_OBJECT_HANDLE);
            final boolean updated = mDatabase.update(TABLE_DOCUMENTS, values, selection, args) != 0;
            mDatabase.setTransactionSuccessful();
            return updated;
        } finally {
            mDatabase.endTransaction();
        }
    }

    int getRowState(String documentId) throws FileNotFoundException {
        try (final Cursor cursor = mDatabase.query(
                TABLE_DOCUMENTS,
                strings(COLUMN_ROW_STATE),
                SELECTION_DOCUMENT_ID,
                strings(documentId),
                null,
                null,
                null)) {
            if (cursor.getCount() == 0) {
                throw new FileNotFoundException();
            }
            cursor.moveToNext();
            return cursor.getInt(0);
        }
    }

    void writeRowSnapshot(String documentId, ContentValues values) throws FileNotFoundException {
        try (final Cursor cursor = mDatabase.query(
                JOIN_ROOTS,
                strings("*"),
                SELECTION_DOCUMENT_ID,
                strings(documentId),
                null,
                null,
                null,
                "1")) {
            if (cursor.getCount() == 0) {
                throw new FileNotFoundException();
            }
            cursor.moveToNext();
            values.clear();
            DatabaseUtils.cursorRowToContentValues(cursor, values);
        }
    }

    void updateObject(String documentId, int deviceId, String parentId, int[] operationsSupported,
                      MtpObjectInfo info) {
        final ContentValues values = new ContentValues();
        getObjectDocumentValues(values, deviceId, parentId, operationsSupported, info);

        mDatabase.beginTransaction();
        try {
            mDatabase.update(
                    TABLE_DOCUMENTS,
                    values,
                    Document.COLUMN_DOCUMENT_ID + " = ?",
                    strings(documentId));
            mDatabase.setTransactionSuccessful();
        } finally {
            mDatabase.endTransaction();
        }
    }

    /**
     * Obtains a document that has already mapped but has unmapped children.
     * @param deviceId Device to find documents.
     * @return Identifier of found document or null.
     */
    @Nullable Identifier getUnmappedDocumentsParent(int deviceId) {
        final String fromClosure =
                TABLE_DOCUMENTS + " AS child INNER JOIN " +
                TABLE_DOCUMENTS + " AS parent ON " +
                "child." + COLUMN_PARENT_DOCUMENT_ID + " = " +
                "parent." + Document.COLUMN_DOCUMENT_ID;
        final String whereClosure =
                "parent." + COLUMN_DEVICE_ID + " = ? AND " +
                "parent." + COLUMN_ROW_STATE + " IN (?, ?) AND " +
                "parent." + COLUMN_DOCUMENT_TYPE + " != ? AND " +
                "child." + COLUMN_ROW_STATE + " = ?";
        try (final Cursor cursor = mDatabase.query(
                fromClosure,
                strings("parent." + COLUMN_DEVICE_ID,
                        "parent." + COLUMN_STORAGE_ID,
                        "parent." + COLUMN_OBJECT_HANDLE,
                        "parent." + Document.COLUMN_DOCUMENT_ID,
                        "parent." + COLUMN_DOCUMENT_TYPE),
                whereClosure,
                strings(deviceId, ROW_STATE_VALID, ROW_STATE_INVALIDATED, DOCUMENT_TYPE_DEVICE,
                        ROW_STATE_DISCONNECTED),
                null,
                null,
                null,
                "1")) {
            if (cursor.getCount() == 0) {
                return null;
            }
            cursor.moveToNext();
            return new Identifier(
                    cursor.getInt(0),
                    cursor.getInt(1),
                    cursor.getInt(2),
                    cursor.getString(3),
                    cursor.getInt(4));
        }
    }

    /**
     * Removes metadata except for data used by outgoingPersistedUriPermissions.
     */
    void cleanDatabase(Uri[] outgoingPersistedUris) {
        mDatabase.beginTransaction();
        try {
            final Set<String> ids = new HashSet<>();
            for (final Uri uri : outgoingPersistedUris) {
                String documentId = DocumentsContract.getDocumentId(uri);
                while (documentId != null) {
                    if (ids.contains(documentId)) {
                        break;
                    }
                    ids.add(documentId);
                    try (final Cursor cursor = mDatabase.query(
                            TABLE_DOCUMENTS,
                            strings(COLUMN_PARENT_DOCUMENT_ID),
                            SELECTION_DOCUMENT_ID,
                            strings(documentId),
                            null,
                            null,
                            null)) {
                        documentId = cursor.moveToNext() ? cursor.getString(0) : null;
                    }
                }
            }
            deleteDocumentsAndRoots(
                    Document.COLUMN_DOCUMENT_ID + " NOT IN " + getIdList(ids), null);
            mDatabase.setTransactionSuccessful();
        } finally {
            mDatabase.endTransaction();
        }
    }

    int getLastBootCount() {
        try (final Cursor cursor = mDatabase.query(
                TABLE_LAST_BOOT_COUNT, strings(COLUMN_VALUE), null, null, null, null, null)) {
            if (cursor.moveToNext()) {
                return cursor.getInt(0);
            } else {
                return 0;
            }
        }
    }

    void setLastBootCount(int value) {
        Preconditions.checkArgumentNonnegative(value, "Boot count must not be negative.");
        mDatabase.beginTransaction();
        try {
            final ContentValues values = new ContentValues();
            values.put(COLUMN_VALUE, value);
            mDatabase.delete(TABLE_LAST_BOOT_COUNT, null, null);
            mDatabase.insert(TABLE_LAST_BOOT_COUNT, null, values);
            mDatabase.setTransactionSuccessful();
        } finally {
            mDatabase.endTransaction();
        }
    }

    private static class OpenHelper extends SQLiteOpenHelper {
        public OpenHelper(Context context, int flags) {
            super(context,
                  flags == FLAG_DATABASE_IN_MEMORY ? null : DATABASE_NAME,
                  null,
                  DATABASE_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL(QUERY_CREATE_DOCUMENTS);
            db.execSQL(QUERY_CREATE_ROOT_EXTRA);
            db.execSQL(QUERY_CREATE_LAST_BOOT_COUNT);
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            db.execSQL("DROP TABLE IF EXISTS " + TABLE_DOCUMENTS);
            db.execSQL("DROP TABLE IF EXISTS " + TABLE_ROOT_EXTRA);
            db.execSQL("DROP TABLE IF EXISTS " + TABLE_LAST_BOOT_COUNT);
            onCreate(db);
        }
    }

    @VisibleForTesting
    static void deleteDatabase(Context context) {
        context.deleteDatabase(DATABASE_NAME);
    }

    static void getDeviceDocumentValues(
            ContentValues values,
            ContentValues extraValues,
            MtpDeviceRecord device) {
        values.clear();
        values.put(COLUMN_DEVICE_ID, device.deviceId);
        values.putNull(COLUMN_STORAGE_ID);
        values.putNull(COLUMN_OBJECT_HANDLE);
        values.putNull(COLUMN_PARENT_DOCUMENT_ID);
        values.put(COLUMN_ROW_STATE, ROW_STATE_VALID);
        values.put(COLUMN_DOCUMENT_TYPE, DOCUMENT_TYPE_DEVICE);
        values.put(COLUMN_MAPPING_KEY, device.deviceKey);
        values.put(Document.COLUMN_MIME_TYPE, Document.MIME_TYPE_DIR);
        values.put(Document.COLUMN_DISPLAY_NAME, device.name);
        values.putNull(Document.COLUMN_SUMMARY);
        values.putNull(Document.COLUMN_LAST_MODIFIED);
        values.put(Document.COLUMN_ICON, R.drawable.ic_root_mtp);
        values.put(Document.COLUMN_FLAGS, getDocumentFlags(
                device.operationsSupported,
                Document.MIME_TYPE_DIR,
                0,
                MtpConstants.PROTECTION_STATUS_NONE,
                DOCUMENT_TYPE_DEVICE));
        values.putNull(Document.COLUMN_SIZE);

        extraValues.clear();
        extraValues.put(Root.COLUMN_FLAGS, getRootFlags(device.operationsSupported));
        extraValues.putNull(Root.COLUMN_AVAILABLE_BYTES);
        extraValues.putNull(Root.COLUMN_CAPACITY_BYTES);
        extraValues.put(Root.COLUMN_MIME_TYPES, "");
    }

    /**
     * Gets {@link ContentValues} for the given root.
     * @param values {@link ContentValues} that receives values.
     * @param extraValues {@link ContentValues} that receives extra values for roots.
     * @param parentDocumentId Parent document ID.
     * @param operationsSupported Array of Operation code supported by the device.
     * @param root Root to be converted {@link ContentValues}.
     */
    static void getStorageDocumentValues(
            ContentValues values,
            ContentValues extraValues,
            String parentDocumentId,
            int[] operationsSupported,
            MtpRoot root) {
        values.clear();
        values.put(COLUMN_DEVICE_ID, root.mDeviceId);
        values.put(COLUMN_STORAGE_ID, root.mStorageId);
        values.putNull(COLUMN_OBJECT_HANDLE);
        values.put(COLUMN_PARENT_DOCUMENT_ID, parentDocumentId);
        values.put(COLUMN_ROW_STATE, ROW_STATE_VALID);
        values.put(COLUMN_DOCUMENT_TYPE, DOCUMENT_TYPE_STORAGE);
        values.put(Document.COLUMN_MIME_TYPE, Document.MIME_TYPE_DIR);
        values.put(Document.COLUMN_DISPLAY_NAME, root.mDescription);
        values.putNull(Document.COLUMN_SUMMARY);
        values.putNull(Document.COLUMN_LAST_MODIFIED);
        values.put(Document.COLUMN_ICON, R.drawable.ic_root_mtp);
        values.put(Document.COLUMN_FLAGS, getDocumentFlags(
                operationsSupported,
                Document.MIME_TYPE_DIR,
                0,
                MtpConstants.PROTECTION_STATUS_NONE,
                DOCUMENT_TYPE_STORAGE));
        values.put(Document.COLUMN_SIZE, root.mMaxCapacity - root.mFreeSpace);

        extraValues.put(Root.COLUMN_FLAGS, getRootFlags(operationsSupported));
        extraValues.put(Root.COLUMN_AVAILABLE_BYTES, root.mFreeSpace);
        extraValues.put(Root.COLUMN_CAPACITY_BYTES, root.mMaxCapacity);
        extraValues.put(Root.COLUMN_MIME_TYPES, "");
    }

    /**
     * Gets {@link ContentValues} for the given MTP object.
     * @param values {@link ContentValues} that receives values.
     * @param deviceId Device ID of the object.
     * @param parentId Parent document ID of the object.
     * @param info MTP object info.
     */
    static void getObjectDocumentValues(
            ContentValues values, int deviceId, String parentId,
            int[] operationsSupported, MtpObjectInfo info) {
        values.clear();
        final String mimeType = getMimeType(info);
        values.put(COLUMN_DEVICE_ID, deviceId);
        values.put(COLUMN_STORAGE_ID, info.getStorageId());
        values.put(COLUMN_OBJECT_HANDLE, info.getObjectHandle());
        values.put(COLUMN_PARENT_DOCUMENT_ID, parentId);
        values.put(COLUMN_ROW_STATE, ROW_STATE_VALID);
        values.put(COLUMN_DOCUMENT_TYPE, DOCUMENT_TYPE_OBJECT);
        values.put(Document.COLUMN_MIME_TYPE, mimeType);
        values.put(Document.COLUMN_DISPLAY_NAME, info.getName());
        values.putNull(Document.COLUMN_SUMMARY);
        values.put(
                Document.COLUMN_LAST_MODIFIED,
                info.getDateModified() != 0 ? info.getDateModified() : null);
        values.putNull(Document.COLUMN_ICON);
        values.put(Document.COLUMN_FLAGS, getDocumentFlags(
                operationsSupported, mimeType, info.getThumbCompressedSizeLong(),
                info.getProtectionStatus(), DOCUMENT_TYPE_OBJECT));
        values.put(Document.COLUMN_SIZE, info.getCompressedSizeLong());
    }

    private static String getMimeType(MtpObjectInfo info) {
        if (info.getFormat() == MtpConstants.FORMAT_ASSOCIATION) {
            return DocumentsContract.Document.MIME_TYPE_DIR;
        }

        final String formatCodeMimeType = MediaFile.getMimeTypeForFormatCode(info.getFormat());
        final String mediaFileMimeType = MediaFile.getMimeTypeForFile(info.getName());

        // Format code can be mapped with multiple mime types, e.g. FORMAT_MPEG is mapped with
        // audio/mp4 and video/mp4.
        // As file extension contains more information than format code, returns mime type obtained
        // from file extension if it is consistent with format code.
        if (mediaFileMimeType != null &&
                MediaFile.getFormatCode("", mediaFileMimeType) == info.getFormat()) {
            return mediaFileMimeType;
        }
        if (formatCodeMimeType != null) {
            return formatCodeMimeType;
        }
        if (mediaFileMimeType != null) {
            return mediaFileMimeType;
        }
        // We don't know the file type.
        return "application/octet-stream";
    }

    private static int getRootFlags(int[] operationsSupported) {
        int rootFlag = Root.FLAG_SUPPORTS_IS_CHILD;
        if (MtpDeviceRecord.isWritingSupported(operationsSupported)) {
            rootFlag |= Root.FLAG_SUPPORTS_CREATE;
        }
        return rootFlag;
    }

    private static int getDocumentFlags(
            @Nullable int[] operationsSupported, String mimeType, long thumbnailSize,
            int protectionState, @DocumentType int documentType) {
        int flag = 0;
        if (!mimeType.equals(Document.MIME_TYPE_DIR) &&
                MtpDeviceRecord.isWritingSupported(operationsSupported) &&
                protectionState == MtpConstants.PROTECTION_STATUS_NONE) {
            flag |= Document.FLAG_SUPPORTS_WRITE;
        }
        if (MtpDeviceRecord.isSupported(
                operationsSupported, MtpConstants.OPERATION_DELETE_OBJECT) &&
                (protectionState == MtpConstants.PROTECTION_STATUS_NONE ||
                 protectionState == MtpConstants.PROTECTION_STATUS_NON_TRANSFERABLE_DATA) &&
                documentType == DOCUMENT_TYPE_OBJECT) {
            flag |= Document.FLAG_SUPPORTS_DELETE;
        }
        if (mimeType.equals(Document.MIME_TYPE_DIR) &&
                MtpDeviceRecord.isWritingSupported(operationsSupported) &&
                protectionState == MtpConstants.PROTECTION_STATUS_NONE) {
            flag |= Document.FLAG_DIR_SUPPORTS_CREATE;
        }
        if (thumbnailSize > 0) {
            flag |= Document.FLAG_SUPPORTS_THUMBNAIL;
        }
        return flag;
    }

    static String[] strings(Object... args) {
        final String[] results = new String[args.length];
        for (int i = 0; i < args.length; i++) {
            results[i] = Objects.toString(args[i]);
        }
        return results;
    }

    private static String getIdList(Set<String> ids) {
        String result = "(";
        for (final String id : ids) {
            if (result.length() > 1) {
                result += ",";
            }
            result += id;
        }
        result += ")";
        return result;
    }
}
