package SBC.NanoPi;

import java.text.MessageFormat;

import com.sun.jna.Platform;
import com.sun.jna.platform.linux.Fcntl;

import anywheresoftware.b4a.BA;
import jGPIO.input_event;
import jGPIO.mycodes;

@BA.ShortName("Nanopi_IR_Receiver")
@BA.Events(values= {
		"log(msg as string)",
		"newvalue(tipe as int, code as int, value as int)"
})
public class Nanopi_IR_Receiver {
	private BA ba;
	private String event;
	private Object Me;
	private boolean need_log_event = false;
	private boolean need_newvalue_event = false;
	private int boardtype;
	private LibFriendlyArmHardware wiringnp;
	private static int irFD;
	private final String driver_module = "matrix_ir_recv";
	
	public void Initialize(BA bax, LibFriendlyArmHardware wiringNP, String eventname) {
		this.ba = bax;
		this.event = eventname;
		this.wiringnp = wiringNP;
		Me = this;
		check_events();
	}
	
	
	
	public boolean Open(String IR_Name, int pin) {
		if (Platform.isLinux()) {
			if (Platform.isARM()) {
				if (!Platform.is64Bit()) {
					if (wiringnp==null) wiringnp = new LibFriendlyArmHardware();
					boardtype = wiringnp.boardInit();
					if (boardtype>0) {
						modprobe(driver_module, pin);
						
						irFD = wiringnp.openHW(IR_Name, Fcntl.O_RDWR);
						if (irFD>0) {
							Thread tt = new Thread(()->{
								int retsize = 0;
								input_event event = new input_event();
								while(true) {
									if (wiringnp.selectHW(irFD, 0, 0)==1) {
										retsize = wiringnp.readHW(irFD, event.getPointer(), event.size());
										// convert dari signed short --> unsigned value
										raise_newvalue(event.type & 0xFFFF, event.code & 0xFFFF, event.value);
										raise_log(MessageFormat.format("readHW retsize={0}, type={1}, code={2}, value{3}", retsize, event.type, event.code, event.value));
									} else break;
								}
								Close();
								 
							});
							tt.start();
							return true;
						} else {
							raise_log("Nanopi_IR_Receiver Open failed, openHW failed");
							rmmod(driver_module);
						}
					} else raise_log("Nanopi_IR_Receiver Open failed, boardInit failed");
				} else raise_log("Nanopi_IR_Receiver Open failed, current driver works on 32bit model");
			} else raise_log("Nanopi_IR_Receiver Open failed, must run on ARM Architecture");
		} else raise_log("Nanopi_IR_Receiver Open failed, must run on Linux");
		return false;
	}
	
	public void Close() {
		if (irFD>0) {
			wiringnp.closeHW(irFD);
			irFD = 0;
		}
	}
	
	//TODO belum tau caranya
	private void modprobe(String drivermodule, int pin) {
		//sprintf(modStr, "modprobe %s gpio=%d", DRIVER_MODULE, pintoGPIO(pin));
	    //system(modStr);
	}
	
	//TODO belum tau caranya
	private void rmmod(String drivermodule) {
		//system("rmmod "DRIVER_MODULE);
	}
	
	private void check_events() {
		if (ba!=null) {
			if (mycodes.ValidString(event)) {
				need_log_event = ba.subExists(event+"_log");
				need_newvalue_event = ba.subExists(event+"_newvalue");
			}
		}
	}
	
	private void raise_log(String msg) {
		if (need_log_event) {
			ba.raiseEventFromDifferentThread(Me, null, 0, event+"_log", false, new Object[] {msg});
		}
	}
	
	private void raise_newvalue(int type, int code, int value) {
		if (need_newvalue_event) {
			ba.raiseEventFromDifferentThread(Me, null, 0, event+"_newvalue", false, new Object[] {type, code, value});
		}
	}
}
