/*
 * Copyright (C) 2010 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 android.mtp;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.os.CancellationSignal;
import android.os.ParcelFileDescriptor;

import com.android.internal.util.Preconditions;

import java.io.IOException;

/**
 * This class represents an MTP or PTP device connected on the USB host bus. An application can
 * instantiate an object of this type, by referencing an attached {@link
 * android.hardware.usb.UsbDevice} and then use methods in this class to get information about the
 * device and objects stored on it, as well as open the connection and transfer data.
 */
public final class MtpDevice {

    private static final String TAG = "MtpDevice";

    private final UsbDevice mDevice;

    static {
        System.loadLibrary("media_jni");
    }

    /**
     * MtpClient constructor
     *
     * @param device the {@link android.hardware.usb.UsbDevice} for the MTP or PTP device
     */
    public MtpDevice(UsbDevice device) {
        mDevice = device;
    }

    /**
     * Opens the MTP device.  Once the device is open it takes ownership of the
     * {@link android.hardware.usb.UsbDeviceConnection}.
     * The connection will be closed when you call {@link #close()}
     * The connection will also be closed if this method fails.
     *
     * @param connection an open {@link android.hardware.usb.UsbDeviceConnection} for the device
     * @return true if the device was successfully opened.
     */
    public boolean open(UsbDeviceConnection connection) {
        boolean result = native_open(mDevice.getDeviceName(), connection.getFileDescriptor());
        if (!result) {
            connection.close();
        }
        return result;
    }

    /**
     * Closes all resources related to the MtpDevice object.
     * After this is called, the object can not be used until {@link #open} is called again
     * with a new {@link android.hardware.usb.UsbDeviceConnection}.
     */
    public void close() {
        native_close();
    }

    @Override
    protected void finalize() throws Throwable {
        try {
            native_close();
        } finally {
            super.finalize();
        }
    }

    /**
     * Returns the name of the USB device
     * This returns the same value as {@link android.hardware.usb.UsbDevice#getDeviceName}
     * for the device's {@link android.hardware.usb.UsbDevice}
     *
     * @return the device name
     */
    public String getDeviceName() {
        return mDevice.getDeviceName();
    }

    /**
     * Returns the USB ID of the USB device.
     * This returns the same value as {@link android.hardware.usb.UsbDevice#getDeviceId}
     * for the device's {@link android.hardware.usb.UsbDevice}
     *
     * @return the device ID
     */
    public int getDeviceId() {
        return mDevice.getDeviceId();
    }

    @Override
    public String toString() {
        return mDevice.getDeviceName();
    }

    /**
     * Returns the {@link MtpDeviceInfo} for this device
     *
     * @return the device info
     */
    public MtpDeviceInfo getDeviceInfo() {
        return native_get_device_info();
    }

    /**
     * Returns the list of IDs for all storage units on this device
     * Information about each storage unit can be accessed via {@link #getStorageInfo}.
     *
     * @return the list of storage IDs
     */
    public int[] getStorageIds() {
        return native_get_storage_ids();
    }

    /**
     * Returns the list of object handles for all objects on the given storage unit,
     * with the given format and parent.
     * Information about each object can be accessed via {@link #getObjectInfo}.
     *
     * @param storageId the storage unit to query
     * @param format the format of the object to return, or zero for all formats
     * @param objectHandle the parent object to query, -1 for the storage root,
     *     or zero for all objects
     * @return the object handles
     */
    public int[] getObjectHandles(int storageId, int format, int objectHandle) {
        return native_get_object_handles(storageId, format, objectHandle);
    }

    /**
     * Returns the data for an object as a byte array.
     * This call may block for an arbitrary amount of time depending on the size
     * of the data and speed of the devices.
     *
     * @param objectHandle handle of the object to read
     * @param objectSize the size of the object (this should match
     *      {@link MtpObjectInfo#getCompressedSize})
     * @return the object's data, or null if reading fails
     */
    public byte[] getObject(int objectHandle, int objectSize) {
        Preconditions.checkArgumentNonnegative(objectSize, "objectSize should not be negative");
        return native_get_object(objectHandle, objectSize);
    }

    /**
     * Obtains object bytes in the specified range and writes it to an array.
     * This call may block for an arbitrary amount of time depending on the size
     * of the data and speed of the devices.
     *
     * @param objectHandle handle of the object to read
     * @param offset Start index of reading range. It must be a non-negative value at most
     *     0xffffffff.
     * @param size Size of reading range. It must be a non-negative value at most Integer.MAX_VALUE
     *     or 0xffffffff. If 0xffffffff is specified, the method obtains the full bytes of object.
     * @param buffer Array to write data.
     * @return Size of bytes that are actually read.
     */
    public long getPartialObject(int objectHandle, long offset, long size, byte[] buffer)
            throws IOException {
        return native_get_partial_object(objectHandle, offset, size, buffer);
    }

    /**
     * Obtains object bytes in the specified range and writes it to an array.
     * This call may block for an arbitrary amount of time depending on the size
     * of the data and speed of the devices.
     *
     * This is a vender-extended operation supported by Android that enables us to pass
     * unsigned 64-bit offset. Check if the MTP device supports the operation by using
     * {@link MtpDeviceInfo#getOperationsSupported()}.
     *
     * @param objectHandle handle of the object to read
     * @param offset Start index of reading range. It must be a non-negative value.
     * @param size Size of reading range. It must be a non-negative value at most Integer.MAX_VALUE.
     * @param buffer Array to write data.
     * @return Size of bytes that are actually read.
     * @see MtpConstants#OPERATION_GET_PARTIAL_OBJECT_64
     */
    public long getPartialObject64(int objectHandle, long offset, long size, byte[] buffer)
            throws IOException {
        return native_get_partial_object_64(objectHandle, offset, size, buffer);
    }

    /**
     * Returns the thumbnail data for an object as a byte array.
     * The size and format of the thumbnail data can be determined via
     * {@link MtpObjectInfo#getThumbCompressedSize} and
     * {@link MtpObjectInfo#getThumbFormat}.
     * For typical devices the format is JPEG.
     *
     * @param objectHandle handle of the object to read
     * @return the object's thumbnail, or null if reading fails
     */
    public byte[] getThumbnail(int objectHandle) {
        return native_get_thumbnail(objectHandle);
    }

    /**
     * Retrieves the {@link MtpStorageInfo} for a storage unit.
     *
     * @param storageId the ID of the storage unit
     * @return the MtpStorageInfo
     */
    public MtpStorageInfo getStorageInfo(int storageId) {
        return native_get_storage_info(storageId);
    }

    /**
     * Retrieves the {@link MtpObjectInfo} for an object.
     *
     * @param objectHandle the handle of the object
     * @return the MtpObjectInfo
     */
    public MtpObjectInfo getObjectInfo(int objectHandle) {
        return native_get_object_info(objectHandle);
    }

    /**
     * Deletes an object on the device.  This call may block, since
     * deleting a directory containing many files may take a long time
     * on some devices.
     *
     * @param objectHandle handle of the object to delete
     * @return true if the deletion succeeds
     */
    public boolean deleteObject(int objectHandle) {
        return native_delete_object(objectHandle);
    }

    /**
     * Retrieves the object handle for the parent of an object on the device.
     *
     * @param objectHandle handle of the object to query
     * @return the parent's handle, or zero if it is in the root of the storage
     */
    public long getParent(int objectHandle) {
        return native_get_parent(objectHandle);
    }

    /**
     * Retrieves the ID of the storage unit containing the given object on the device.
     *
     * @param objectHandle handle of the object to query
     * @return the object's storage unit ID
     */
    public long getStorageId(int objectHandle) {
        return native_get_storage_id(objectHandle);
    }

    /**
     * Copies the data for an object to a file in external storage.
     * This call may block for an arbitrary amount of time depending on the size
     * of the data and speed of the devices.
     *
     * @param objectHandle handle of the object to read
     * @param destPath path to destination for the file transfer.
     *      This path should be in the external storage as defined by
     *      {@link android.os.Environment#getExternalStorageDirectory}
     * @return true if the file transfer succeeds
     */
    public boolean importFile(int objectHandle, String destPath) {
        return native_import_file(objectHandle, destPath);
    }

    /**
     * Copies the data for an object to a file descriptor.
     * This call may block for an arbitrary amount of time depending on the size
     * of the data and speed of the devices. The file descriptor is not closed
     * on completion, and must be done by the caller.
     *
     * @param objectHandle handle of the object to read
     * @param descriptor file descriptor to write the data to for the file transfer.
     * @return true if the file transfer succeeds
     */
    public boolean importFile(int objectHandle, ParcelFileDescriptor descriptor) {
        return native_import_file(objectHandle, descriptor.getFd());
    }

    /**
     * Copies the data for an object from a file descriptor.
     * This call may block for an arbitrary amount of time depending on the size
     * of the data and speed of the devices. The file descriptor is not closed
     * on completion, and must be done by the caller.
     *
     * @param objectHandle handle of the target file
     * @param size size of the file in bytes
     * @param descriptor file descriptor to read the data from.
     * @return true if the file transfer succeeds
     */
    public boolean sendObject(int objectHandle, long size, ParcelFileDescriptor descriptor) {
        return native_send_object(objectHandle, size, descriptor.getFd());
    }

    /**
     * Uploads an object metadata for a new entry. The {@link MtpObjectInfo} can be
     * created with the {@link MtpObjectInfo.Builder} class.
     *
     * The returned {@link MtpObjectInfo} has the new object handle field filled in.
     *
     * @param info metadata of the entry
     * @return object info of the created entry or null if the operation failed.
     */
    public MtpObjectInfo sendObjectInfo(MtpObjectInfo info) {
        return native_send_object_info(info);
    }

    /**
     * Reads an event from the device. It blocks the current thread until it gets an event.
     * It throws OperationCanceledException if it is cancelled by signal.
     *
     * @param signal signal for cancellation
     * @return obtained event
     * @throws IOException
     */
    public @NonNull MtpEvent readEvent(@Nullable CancellationSignal signal) throws IOException {
        final int handle = native_submit_event_request();
        Preconditions.checkState(handle >= 0, "Other thread is reading an event.");

        if (signal != null) {
            signal.setOnCancelListener(new CancellationSignal.OnCancelListener() {
                @Override
                public void onCancel() {
                    native_discard_event_request(handle);
                }
            });
        }

        try {
            return native_reap_event_request(handle);
        } finally {
            if (signal != null) {
                signal.setOnCancelListener(null);
            }
        }
    }

    /**
     * Returns object size in 64-bit integer.
     *
     * Though MtpObjectInfo#getCompressedSize returns the object size in 32-bit unsigned integer,
     * this method returns the object size in 64-bit integer from the object property. Thus it can
     * fetch 4GB+ object size correctly. If the device does not support objectSize property, it
     * throws IOException.
     * @hide
     */
    public long getObjectSizeLong(int handle, int format) throws IOException {
        return native_get_object_size_long(handle, format);
    }

    // used by the JNI code
    private long mNativeContext;

    private native boolean native_open(String deviceName, int fd);
    private native void native_close();
    private native MtpDeviceInfo native_get_device_info();
    private native int[] native_get_storage_ids();
    private native MtpStorageInfo native_get_storage_info(int storageId);
    private native int[] native_get_object_handles(int storageId, int format, int objectHandle);
    private native MtpObjectInfo native_get_object_info(int objectHandle);
    private native byte[] native_get_object(int objectHandle, long objectSize);
    private native long native_get_partial_object(
            int objectHandle, long offset, long objectSize, byte[] buffer) throws IOException;
    private native int native_get_partial_object_64(
            int objectHandle, long offset, long objectSize, byte[] buffer) throws IOException;
    private native byte[] native_get_thumbnail(int objectHandle);
    private native boolean native_delete_object(int objectHandle);
    private native int native_get_parent(int objectHandle);
    private native int native_get_storage_id(int objectHandle);
    private native boolean native_import_file(int objectHandle, String destPath);
    private native boolean native_import_file(int objectHandle, int fd);
    private native boolean native_send_object(int objectHandle, long size, int fd);
    private native MtpObjectInfo native_send_object_info(MtpObjectInfo info);
    private native int native_submit_event_request() throws IOException;
    private native MtpEvent native_reap_event_request(int handle) throws IOException;
    private native void native_discard_event_request(int handle);
    private native long native_get_object_size_long(int handle, int format) throws IOException;
}
