/*
 * BRLTTY - A background process providing access to the console screen (when in
 *          text mode) for a blind person using a refreshable braille display.
 *
 * Copyright (C) 1995-2018 by The BRLTTY Developers.
 *
 * BRLTTY comes with ABSOLUTELY NO WARRANTY.
 *
 * This is free software, placed under the terms of the
 * GNU Lesser General Public License, as published by the Free Software
 * Foundation; either version 2.1 of the License, or (at your option) any
 * later version. Please see the file LICENSE-LGPL for details.
 *
 * Web Page: http://brltty.com/
 *
 * This software is maintained by Dave Mielke <dave@mielke.cc>.
 */

package org.a11y.brltty.android;

import java.util.Collection;
import java.util.Map;

import android.os.Build;
import android.content.Context;
import android.hardware.usb.*;

public final class UsbDeviceCollection extends DeviceCollection {
  public static final String DEVICE_QUALIFIER = "usb";

  @Override
  public final String getQualifier () {
    return DEVICE_QUALIFIER;
  }

  private final UsbManager manager;
  private final Map<String, UsbDevice> map;
  private final Collection<UsbDevice> devices;

  public UsbDeviceCollection (Context context) {
    super();
    manager = (UsbManager)context.getSystemService(Context.USB_SERVICE);
    map = manager.getDeviceList();
    devices = map.values();
  }

  private final String getManufacturerName (UsbDevice device) {
    if (ApplicationUtilities.haveSdkVersion(Build.VERSION_CODES.LOLLIPOP)) {
      return device.getManufacturerName();
    } else {
      return null;
    }
  }

  private final String getProductName (UsbDevice device) {
    if (ApplicationUtilities.haveSdkVersion(Build.VERSION_CODES.LOLLIPOP)) {
      return device.getProductName();
    } else {
      return null;
    }
  }

  private final String getSerialNumber (UsbDevice device) {
    if (ApplicationUtilities.haveSdkVersion(Build.VERSION_CODES.LOLLIPOP)) {
      return device.getSerialNumber();
    } else {
      UsbDeviceConnection connection = manager.openDevice(device);
      if (connection == null) return null;

      try {
        return connection.getSerial();
      } finally {
        connection.close();
      }
    }
  }

  @Override
  public final String[] makeValues () {
    StringMaker<UsbDevice> stringMaker = new StringMaker<UsbDevice>() {
      @Override
      public String makeString (UsbDevice device) {
        return device.getDeviceName();
      }
    };

    return makeStringArray(devices, stringMaker);
  }

  @Override
  public final String[] makeLabels () {
    StringMaker<UsbDevice> stringMaker = new StringMaker<UsbDevice>() {
      @Override
      public String makeString (UsbDevice device) {
        StringBuilder label = new StringBuilder();

        label.append(
          String.format(
            "[%04X:%04X]",
            device.getVendorId(),
            device.getProductId()
          )
        );

        boolean first = true;
        String[] components = new String[] {
          getManufacturerName(device),
          getProductName(device),
          getSerialNumber(device)
        };

        for (String component : components) {
          if (component == null) continue;
          if (component.isEmpty()) continue;

          if (first) {
            first = false;
          } else {
            label.append(',');
          }

          label.append(' ');
          label.append(component);
        }

        return label.toString();
      }
    };

    return makeStringArray(devices, stringMaker);
  }

  @Override
  protected final void putParameters (Map<String, String> parameters, String value) {
    UsbDevice device = map.get(value);
    parameters.put("vendorIdentifier", Integer.toString(device.getVendorId()));
    parameters.put("productIdentifier", Integer.toString(device.getProductId()));
    parameters.put("serialNumber", getSerialNumber(device));
  }
}

@@ -2768,166 +2768,12 @@
     
-label.append(%0A          String.format(%0A            %22%5B%2504X:%2504X%5D%22,%0A            device.getVendorId(),%0A            device.getProductId()%0A          )%0A        );%0A%0A
+%7B%0A  
     
@@ -2798,24 +2798,26 @@
 = true;%0A
+%0A 
         
 String%5B%5D
@@ -2804,24 +2804,25 @@
 ;%0A%0A         
+ 
 String%5B%5D com
@@ -2856,16 +2856,18 @@
         
+  
 getManuf
@@ -2897,16 +2897,18 @@
         
+ 
+ 
 getProdu
@@ -2915,32 +2915,34 @@
 ctName(device),%0A
+  
           getSer
@@ -2963,28 +2963,32 @@
 ce)%0A        
+  
 %7D;%0A%0A
+  
         for 
@@ -3023,32 +3023,34 @@
 ts) %7B%0A          
+  
 if (component ==
@@ -3066,16 +3066,60 @@
 ntinue;%0A
+            component = component.trim();%0A  
         
@@ -3162,24 +3162,26 @@
 %0A%0A          
+  
 if (first) %7B
@@ -3177,24 +3177,26 @@
 f (first) %7B%0A
+  
             
@@ -3216,24 +3216,26 @@
 ;%0A          
+  
 %7D else %7B%0A   
@@ -3227,24 +3227,26 @@
    %7D else %7B%0A
+  
             
@@ -3266,32 +3266,34 @@
 ',');%0A          
+  
 %7D%0A%0A          lab
@@ -3280,32 +3280,58 @@
     %7D%0A%0A         
+   if (label.length() %3E 0)
  label.append(' 
@@ -3330,24 +3330,26 @@
 ppend(' ');%0A
+  
           la
@@ -3371,16 +3371,253 @@
 onent);%0A
+          %7D%0A        %7D%0A%0A        if (label.length() == 0) %7B%0A          label.append(%0A            String.format(%0A              %22%5B%2504X:%2504X%5D%22,%0A              device.getVendorId(),%0A              device.getProductId()%0A            )%0A          );%0A
         

Fix the way that USB device labels are generated. (dm)