/*
 * 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 android.content.Context;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.mtp.MtpConstants;
import android.mtp.MtpDevice;
import android.mtp.MtpDeviceInfo;
import android.mtp.MtpEvent;
import android.mtp.MtpObjectInfo;
import android.os.CancellationSignal;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import android.util.SparseArray;

import com.android.internal.annotations.VisibleForTesting;
import com.android.mtp.exceptions.BusyDeviceException;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;

/**
 * The model wrapping android.mtp API.
 */
class MtpManager {
    final static int OBJECT_HANDLE_ROOT_CHILDREN = -1;

    /**
     * Subclass for PTP.
     */
    private static final int SUBCLASS_STILL_IMAGE_CAPTURE = 1;

    /**
     * Subclass for Android style MTP.
     */
    private static final int SUBCLASS_MTP = 0xff;

    /**
     * Protocol for Picture Transfer Protocol (PIMA 15470).
     */
    private static final int PROTOCOL_PICTURE_TRANSFER = 1;

    /**
     * Protocol for Android style MTP.
     */
    private static final int PROTOCOL_MTP = 0;


    private final UsbManager mManager;
    // TODO: Save and restore the set of opened device.
    private final SparseArray<MtpDevice> mDevices = new SparseArray<>();

    MtpManager(Context context) {
        mManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
    }

    synchronized void openDevice(int deviceId) throws IOException {
        UsbDevice rawDevice = null;
        for (final UsbDevice candidate : mManager.getDeviceList().values()) {
            if (candidate.getDeviceId() == deviceId) {
                rawDevice = candidate;
                break;
            }
        }

        if (rawDevice == null) {
            throw new IOException("Not found USB device: " + deviceId);
        }

        if (!mManager.hasPermission(rawDevice)) {
            mManager.grantPermission(rawDevice);
            if (!mManager.hasPermission(rawDevice)) {
                throw new IOException("Failed to grant a device permission.");
            }
        }

        final MtpDevice device = new MtpDevice(rawDevice);

        final UsbDeviceConnection connection = mManager.openDevice(rawDevice);
        if (connection == null) {
            throw new IOException("Failed to open a USB connection.");
        }

        if (!device.open(connection)) {
            // We cannot open connection when another application use the device.
            throw new BusyDeviceException();
        }

        // Handle devices that fail to obtain storages just after opening a MTP session.
        final int[] storageIds = device.getStorageIds();
        if (storageIds == null) {
            throw new IOException("Not found MTP storages in the device.");
        }

        mDevices.put(deviceId, device);
    }

    synchronized void closeDevice(int deviceId) throws IOException {
        getDevice(deviceId).close();
        mDevices.remove(deviceId);
    }

    synchronized MtpDeviceRecord[] getDevices() {
        final ArrayList<MtpDeviceRecord> devices = new ArrayList<>();
        for (UsbDevice device : mManager.getDeviceList().values()) {
            if (!isMtpDevice(device)) {
                continue;
            }
            final MtpDevice mtpDevice = mDevices.get(device.getDeviceId());
            final boolean opened = mtpDevice != null;
            final String name = device.getProductName();
            MtpRoot[] roots;
            int[] operationsSupported = null;
            int[] eventsSupported = null;
            if (opened) {
                try {
                    roots = getRoots(device.getDeviceId());
                } catch (IOException exp) {
                    Log.e(MtpDocumentsProvider.TAG, "Failed to open device", exp);
                    // If we failed to fetch roots for the device, we still returns device model
                    // with an empty set of roots so that the device is shown DocumentsUI as long as
                    // the device is physically connected.
                    roots = new MtpRoot[0];
                }
                final MtpDeviceInfo info = mtpDevice.getDeviceInfo();
                if (info != null) {
                    operationsSupported = mtpDevice.getDeviceInfo().getOperationsSupported();
                    eventsSupported = mtpDevice.getDeviceInfo().getEventsSupported();
                }
            } else {
                roots = new MtpRoot[0];
            }
            devices.add(new MtpDeviceRecord(
                    device.getDeviceId(), name, device.getSerialNumber(), opened, roots,
                    operationsSupported, eventsSupported));
        }
        return devices.toArray(new MtpDeviceRecord[devices.size()]);
    }

    synchronized int[] getOpenedDeviceIds() {
        final int[] result = new int[mDevices.size()];
        for (int i = 0; i < result.length; i++) {
            result[i] = mDevices.keyAt(i);
        }
        return result;
    }

    MtpObjectInfo getObjectInfo(int deviceId, int objectHandle)
            throws IOException {
        final MtpDevice device = getDevice(deviceId);
        synchronized (device) {
            return device.getObjectInfo(objectHandle);
        }
    }

    int[] getObjectHandles(int deviceId, int storageId, int parentObjectHandle)
            throws IOException {
        final MtpDevice device = getDevice(deviceId);
        synchronized (device) {
            return device.getObjectHandles(storageId, 0 /* all format */, parentObjectHandle);
        }
    }

    byte[] getObject(int deviceId, int objectHandle, int expectedSize)
            throws IOException {
        final MtpDevice device = getDevice(deviceId);
        synchronized (device) {
            return device.getObject(objectHandle, expectedSize);
        }
    }

    @VisibleForTesting
    long getPartialObject(int deviceId, int objectHandle, long offset, long size, byte[] buffer)
            throws IOException {
        final MtpDevice device = getDevice(deviceId);
        synchronized (device) {
            return device.getPartialObject(objectHandle, offset, size, buffer);
        }
    }

    byte[] getThumbnail(int deviceId, int objectHandle) throws IOException {
        final MtpDevice device = getDevice(deviceId);
        synchronized (device) {
            return device.getThumbnail(objectHandle);
        }
    }

    void deleteDocument(int deviceId, int objectHandle) throws IOException {
        final MtpDevice device = getDevice(deviceId);
        synchronized (device) {
            if (!device.deleteObject(objectHandle)) {
                throw new IOException("Failed to delete document");
            }
        }
    }

    int createDocument(int deviceId, MtpObjectInfo objectInfo,
            ParcelFileDescriptor source) throws IOException {
        final MtpDevice device = getDevice(deviceId);
        synchronized (device) {
            final MtpObjectInfo sendObjectInfoResult = device.sendObjectInfo(objectInfo);
            if (sendObjectInfoResult == null) {
                throw new IOException("Failed to create a document");
            }
            if (objectInfo.getFormat() != MtpConstants.FORMAT_ASSOCIATION) {
                if (!device.sendObject(sendObjectInfoResult.getObjectHandle(),
                        sendObjectInfoResult.getCompressedSize(), source)) {
                    throw new IOException("Failed to send contents of a document");
                }
            }
            return sendObjectInfoResult.getObjectHandle();
        }
    }

    int getParent(int deviceId, int objectHandle) throws IOException {
        final MtpDevice device = getDevice(deviceId);
        synchronized (device) {
            final int result = (int) device.getParent(objectHandle);
            if (result < 0) {
                throw new FileNotFoundException("Not found parent object");
            }
            return result;
        }
    }

    void importFile(int deviceId, int objectHandle, ParcelFileDescriptor target)
            throws IOException {
        final MtpDevice device = getDevice(deviceId);
        synchronized (device) {
            device.importFile(objectHandle, target);
        }
    }

    @VisibleForTesting
    MtpEvent readEvent(int deviceId, CancellationSignal signal) throws IOException {
        final MtpDevice device = getDevice(deviceId);
        return device.readEvent(signal);
    }

    private synchronized MtpDevice getDevice(int deviceId) throws IOException {
        final MtpDevice device = mDevices.get(deviceId);
        if (device == null) {
            throw new IOException("USB device " + deviceId + " is not opened.");
        }
        return device;
    }

    private MtpRoot[] getRoots(int deviceId) throws IOException {
        final MtpDevice device = getDevice(deviceId);
        synchronized (device) {
            final int[] storageIds = device.getStorageIds();
            if (storageIds == null) {
                throw new IOException("Failed to obtain storage IDs.");
            }
            final MtpRoot[] results = new MtpRoot[storageIds.length];
            for (int i = 0; i < storageIds.length; i++) {
                results[i] = new MtpRoot(
                        device.getDeviceId(), device.getStorageInfo(storageIds[i]));
            }
            return results;
        }
    }

    static boolean isMtpDevice(UsbDevice device) {
        for (int i = 0; i < device.getInterfaceCount(); i++) {
            final UsbInterface usbInterface = device.getInterface(i);
            if ((usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_STILL_IMAGE &&
                    usbInterface.getInterfaceSubclass() == SUBCLASS_STILL_IMAGE_CAPTURE &&
                    usbInterface.getInterfaceProtocol() == PROTOCOL_PICTURE_TRANSFER)) {
                return true;
            }
            if (usbInterface.getInterfaceClass() == UsbConstants.USB_SUBCLASS_VENDOR_SPEC &&
                    usbInterface.getInterfaceSubclass() == SUBCLASS_MTP &&
                    usbInterface.getInterfaceProtocol() == PROTOCOL_MTP &&
                    usbInterface.getName().equals("MTP")) {
                return true;
            }
        }
        return false;
    }
}
