/*
 * 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
     * @param size Object size. info#getCompressedSize() will be ignored because it does not contain
     *     object size more than 4GB.
     * @return Document ID of added document.
     */
    String putNewDocument(
            int deviceId, String parentDocumentId, int[] operationsSupported, MtpObjectInfo info,
            long size) {
        final ContentValues values = new ContentValues();
        getObjectDocumentValues(
                values, deviceId, parentDocumentId, operationsSupported, info, size);
        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, Long size) {
        final ContentValues values = new ContentValues();
        getObjectDocumentValues(values, deviceId, parentId, operationsSupported, info, size);

        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. getCompressedSize will be ignored.
     * @param size 64-bit size of documents. Negative value is regarded as unknown size.
     */
    static void getObjectDocumentValues(
            ContentValues values, int deviceId, String parentId,
            int[] operationsSupported, MtpObjectInfo info, long size) {
        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));
        if (size >= 0) {
            values.put(Document.COLUMN_SIZE, size);
        } else {
            values.putNull(Document.COLUMN_SIZE);
        }
    }

    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;
    }
}
