package com.example.myapplication.util;

import android.content.Context;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

public class DfuRuntimeGetStateRunnable implements Runnable {

    private final String TAG = "DfuRuntimeGetState";
    private int mIdxInterface;
    private UsbManager mManager = null;
    private UsbDevice mDevice = null;
    private UsbInterface mInterface = null;
    private UsbDeviceConnection mConn = null;
    private Handler mUiHandler = null;

    public DfuRuntimeGetStateRunnable(Context context, Handler uiHandler, UsbDevice device) {
        mIdxInterface = UsbDfuConstants.findDfuRuntimeModeInterface(device);
        if (mIdxInterface != -1) {
            mDevice = device;
            mInterface = device.getInterface(mIdxInterface);
            mManager = (UsbManager)context.getSystemService(Context.USB_SERVICE);
            mUiHandler = uiHandler;
        } else {
            Log.e(TAG,"The device does not have a DFU Runtime Mode Interface.");
        }
    }

    private void logMessageToUi(String textToLog) {
        if (mUiHandler != null) {
            Message msg = mUiHandler.obtainMessage(0, textToLog + System.lineSeparator());
            msg.sendToTarget();
        }
        // Debug
        Log.d(TAG, textToLog);
    }

    @Override
    public void run() {

        // Early Exit if a DFU runtime inteface is not found
        if (mDevice == null) {
            Log.e(TAG, "run() called with device == null!");
            return;
        }

        // Open a UsbDeviceConnection
        mConn = mManager.openDevice(mDevice);
        if (mConn == null) {
            Log.e(TAG, "Could not open device connection!");
            return;
        }

        // Claim interface (may be optional)
        if (!mConn.claimInterface(mInterface, false)) {
            Log.e(TAG, "Failed to claim DFU runtime mode interface!");
        }

        byte[] byteArray = new byte[UsbDfuConstants.DFU_GETSTATE_wLength];

        // =========================================================================================
        // Send DFU_GETSTATE class request
        int result = mConn.controlTransfer(
                UsbDfuConstants.DFU_GETSTATE_bmRequestType, // DFU_DETACH bmRequest
                UsbDfuConstants.DFU_GETSTATE_bRequest, // DFU_DETACH bRequest
                UsbDfuConstants.DFU_GETSTATE_wValue,
                mIdxInterface,
                byteArray,
                UsbDfuConstants.DFU_GETSTATE_wLength,
                UsbDfuConstants.USB_TRANSFER_TIMEOUT);

        // Debug
        if (result < 0) {
            logMessageToUi("Failed to send DFU_GETSTATE. Returned: " + result);
        } else {
            logMessageToUi("Successfully sent DFU_GETSTATE to DFU run-time interface.");
        }

        // Done. Nothing else to do but wait for device self-reset.
        mConn.releaseInterface(mInterface);
        mConn.close();
    }
}
