package net.alphadev.usbstorage;

import android.content.Context;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.hardware.usb.UsbRequest;
import android.util.Log;

import net.alphadev.usbstorage.scsi.CommandBlockWrapper;

import java.io.IOException;
import java.nio.ByteBuffer;

import de.waldheinz.fs.BlockDevice;
import de.waldheinz.fs.ReadOnlyException;

public class UsbBlockDevice implements BlockDevice {

    public final static int DEFAULT_SECTOR_SIZE = 512;
    private static final String LOG_TAG = "Drive Mount";
    private UsbEndpoint mReadEndpoint;
    private UsbEndpoint mWriteEndpoint;
    private UsbInterface mDataInterface;
    private UsbDeviceConnection mConnection;
    private boolean closed;

    public UsbBlockDevice(Context ctx, UsbDevice device) {
        final UsbManager manager = (UsbManager) ctx.getSystemService(Context.USB_SERVICE);
        open(device, manager);
    }

    private void open(UsbDevice device, UsbManager manager) {

        if (!manager.hasPermission(device)) {
            throw new IllegalStateException("You don't have the permission to access this device!");
        }

        for (int i = 0; i < device.getInterfaceCount(); i++) {
            UsbInterface interfaceProbe = device.getInterface(i);
            if (interfaceProbe.getInterfaceClass() == UsbConstants.USB_CLASS_MASS_STORAGE) {
                mDataInterface = device.getInterface(i);
            }
        }

        for (int i = 0; i < mDataInterface.getEndpointCount(); i++) {
            UsbEndpoint endpointProbe = mDataInterface.getEndpoint(i);
            if (endpointProbe.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
                if (endpointProbe.getDirection() == UsbConstants.USB_DIR_IN) {
                    mReadEndpoint = endpointProbe;
                } else {
                    mWriteEndpoint = endpointProbe;
                }
            }
        }

        mConnection = manager.openDevice(device);
        closed = false;
    }

    @Override
    public long getSize() throws IOException {
        checkClosed();

        int retval = send_mass_storage_command(GENERIC_USB.READ_CAPACITY_LENGTH);
        // create a usb request and ask for the drives size.
        // READ_CAPACITY_LENGTH

        return 0;
    }

    @Override
    public void read(long offset, ByteBuffer byteBuffer) throws IOException {
        checkClosed();

        final UsbRequest request = new UsbRequest();
        try {
            request.initialize(mConnection, mReadEndpoint);
            if (!request.queue(byteBuffer, mReadEndpoint.getMaxPacketSize())) {
                throw new IOException("Error queueing request.");
            }

            final UsbRequest response = mConnection.requestWait();
            if (mConnection.requestWait() != request) {
                throw new IOException("Null response");
            }
        } finally {
            request.close();
        }
    }

    private int send_mass_storage_command(int command) {
        CommandBlockWrapper cbw = new CommandBlockWrapper();
        cbw.setSignature((byte) 'U', (byte) 'S', (byte) 'B', (byte) 'C');

        return -1;
    }

    @Override
    public void write(long offset, ByteBuffer byteBuffer) throws ReadOnlyException, IOException, IllegalArgumentException {

    }

    @Override
    public void flush() throws IOException {
        // since we write everything directly to the device there's no need to flush.
    }

    @Override
    public int getSectorSize() throws IOException {
        return DEFAULT_SECTOR_SIZE;
    }

    @Override
    public void close() throws IOException {
        if (mConnection == null) {
            throw new IOException("Already closed");
        }
        mConnection.close();
        mConnection = null;
        closed = true;
    }

    @Override
    public boolean isClosed() {
        return closed;
    }

    @Override
    public boolean isReadOnly() {
        return false;
    }

    private void checkClosed() {
        if (closed) throw new IllegalStateException("device already closed");
    }

    /**
     * Bulk-Only Mass Storage Class specifications
     */
    private static final class BOMS {
        public static final int BOMS_RESET = 0xFF;
        public static final int BOMS_GET_MAX_LUN = 0xFE;
    }

    private static final class GENERIC_USB {
        public static final int READ_CAPACITY_LENGTH = 0x08;
        public static final int READ_STUFF = 0x10;
    }
}

@@ -641,20 +641,20 @@
 lic 
-final 
 static
+ final
  int
@@ -738,16 +738,17 @@
 Mount%22;%0A
+%0A
     priv
@@ -1183,17 +1183,16 @@
 ager) %7B%0A
-%0A
         
@@ -1583,48 +1583,487 @@
     
-mDataInterface = device.getInterface(i);
+if (interfaceProbe.getInterfaceSubclass() == 0x6) %7B%0A                    if (mDataInterface.getInterfaceProtocol() == 0x50) %7B%0A                        mDataInterface = device.getInterface(i);%0A                    %7D else %7B%0A                        throw new UnsupportedOperationException(%22Cannot talk to this USB device!%22);%0A                    %7D%0A                %7D else %7B%0A                    throw new UnsupportedOperationException(%22Cannot talk to this USB device!%22);%0A                %7D
 %0A   

check for boms compatible devices.