package hid;

import org.hid4java.jna.HidApi;
import org.hid4java.jna.HidDeviceInfoStructure;
import org.hid4java.jna.HidDeviceStructure;

import anywheresoftware.b4a.BA;
import anywheresoftware.b4a.objects.collections.List;
import jGPIO.mycodes;

@BA.ShortName("jHID")
@BA.Events(values= {
		"log(msg as string)"
})
public class jHID {

	private BA ba;
	private String event;
	private Object Me;
	
	private boolean initialized = false;
	private boolean need_log_event =false;
	
	/**
	 * Initialize jHID
	 * @param eventname Evantname
	 */
	public void Initialize(BA ba, String eventname) {
		this.ba = ba;
		this.event = eventname;
		Me = this;
		
		check_events();
		init_hidapi();
		initialized = true;
	}
	
	/**
	 * Check if jHID is initialized or not
	 * @return true if already initialized
	 */
	public boolean IsInitialized() {
		return initialized;
	}
	
	/**
	 * Get all attached Hid Device
	 * @return List of HidDeviceInfo object
	 */
	public List getAttachedDevices() {
		return getAttachedDevices(0,0);
	}
	
	/**
	 * Get all attached Hid Device with specific Vendor and Product ID
	 * @param vendorid specific vendor id
	 * @param productid specific product id 
	 * @return List of HidDeviceInfo object
	 */
	public List getAttachedDevices(final int vendorid, final int productid) {
		List result = new List();
		
		HidDeviceInfoStructure root = HidApi.enumerateDevices(vendorid, productid);
		if (root!=null) {
			HidDeviceInfoStructure hid = root;
			do {
				result.Add(new HidDeviceInfo(hid));
				hid = hid.next();
			} while(hid != null);
			
			HidApi.freeEnumeration(root);
		}
		
		return result;
	}
	
	/**
	 * Open a HidDevice
	 * @param vendorId Specific Vendor ID
	 * @param productId specific Product Id
	 * @param serialNumber specific serial Number
	 * @return null if failed
	 */
	public HidDevice open(final int vendorId, final int productId, final String serialNumber) {
		HidDeviceStructure devstruc = HidApi.open(vendorId, productId, serialNumber);
		if (devstruc!=null) {
			return new HidDevice(devstruc, vendorId, productId, serialNumber);
		} else raise_log("open failed, unable to open HidDeviceStructure");
		return null;
	}
	
	/**
	 * Open a HidDevice
	 * @param info HidDeviceInfo object
	 * @return null if failed
	 */
	public HidDevice open(HidDeviceInfo info) {
		if (info!=null) {
			if (mycodes.ValidString(info.getPath())) {
				HidDeviceStructure devstruc = HidApi.open(info.getPath());
				if (devstruc != null) {
					return new HidDevice(devstruc, info.getVendorId(), info.getProductId(), info.getSerialNumber().toString());
				} else raise_log("open failed, unable to open HidDeviceStructure");
			} else raise_log("open failed, HidDeviceInfo path is invalid");
		} else raise_log("open failed, HidDeviceInfo is null");
		return null;
	}
	
	
	
	private void init_hidapi() {
		HidApi.init();
	}
	
	private void check_events() {
		if (ba!=null) {
			if (mycodes.ValidString(event)) {
				need_log_event = ba.subExists(event+"_log");
			}
		}
	}
	
	private void raise_log(String msg) {
		if (need_log_event) ba.raiseEventFromDifferentThread(Me, null, 0, event+"_log", false, new Object[] {msg});
	}
}
