package jGPIO.SPI;

import jGPIO.jGPIO;

//TODO : belum tau caranya
@SuppressWarnings("unused")
public class SPI_BUS {
	private final int O_RDWR = 0x00000002;
	
	private boolean opened = false;
	private String spi_name = "";
	private int spi_handle = -1;
	private SPI_BUS_Event javaevent;
	
	private int mode = 0;
	private int speed = 1000000;
	private int databits = 8;
	private final int min_speed = 500 * 1000;
	private final int max_speed = 32*1000*1000;
	
	/**
	 * Create SPI_BUS object, with default mode 0, speed 1Mhz
	 * @param spi_name : valid spi name , example /dev/spidev0.0
	 */
	public SPI_BUS(String spi_name) {
		
		this.spi_name = spi_name;
	}
	
	/**
	 * Create SPI_BUS Object
	 * @param spi_name : valid spi_name, example /dev/spidev0.0
	 * @param mode : default at mode 0
	 * 		0 = Clock idle low, data is clocked in on rising edge, output data (change) on falling edge
	 * 		1 = Clock idle low, data is clocked in on falling edge, output data (change) on rising edge
	 * 		2 = Clock idle high, data is clocked in on falling edge, output data (change) on rising edge
	 * 		3 = Clock idle high, data is clocked in on rising, edge output data (change) on falling edge 
	 * @param speed : 500Khz - 32Mhz
	 */
	public SPI_BUS(String spi_name, int mode, int speed) {
		this.spi_name = spi_name;
		if ((mode<0) || (mode>3)) mode = 0;
		this.mode = mode;
		if ((speed<min_speed) || (speed>max_speed))  speed = 1000000;
		
		this.speed = speed;
	}
	
	/**
	 * Create SPI_BUS Object
	 * @param spi_name : valid spi_name, example /dev/spidev0.0
	 * @param mode : default at mode 0
	 * 		0 = Clock idle low, data is clocked in on rising edge, output data (change) on falling edge
	 * 		1 = Clock idle low, data is clocked in on falling edge, output data (change) on rising edge
	 * 		2 = Clock idle high, data is clocked in on falling edge, output data (change) on rising edge
	 * 		3 = Clock idle high, data is clocked in on rising, edge output data (change) on falling edge 
	 * @param speed : 500Khz - 32Mhz
	 * @param databits : default at 8 bits
	 */
	public SPI_BUS(String spi_name, int mode, int speed, int databits) {
		this.spi_name = spi_name;
		
		if ((mode<0) || (mode>3)) mode = 0;
		this.mode = mode;
		
		if ((speed<min_speed) || (speed>max_speed))  speed = 1000000;
		this.speed = speed;
		
		this.databits = databits;
	}
	
	/**
	 * Set Java Event
	 * @param event
	 */
	public void SetJavaEvent(SPI_BUS_Event event) {
		javaevent = event;
	}
	
	
	/**
	 * Open BUS
	 * @return true if success
	 */
	public boolean Open_Bus() {
		opened = false;
		if (spi_name=="") return false;
		
		spi_handle = jGPIO.libC.open(spi_name, O_RDWR);
		if (spi_handle<0) {
			raise_log("Open_Bus failed");
			opened = false;			
		}
		else {
			// initialize mode
			
			
			// initialize speed
			
			// initialize databits
			
			raise_log("Open_Bus success");
			opened = true;
		}
			
		return opened;
	}
	
	public void Close_Bus() {
		if (spi_handle>=0) {
			jGPIO.libC.close(spi_handle);
			
		}
		spi_handle = -1;
		opened = false;
		this.spi_name="";
		raise_log("SPI BUS closed");
	}
	
	/**
	 * Write data
	 * @param bb : bytes of data
	 * @return number of bytes written, or 0 if failed
	 */
	public int Write(byte[] bb) {
		if (opened) {
			if (spi_handle>=0) {
				int writeresult =  jGPIO.libC.write(spi_handle, bb, bb.length);
				if (writeresult==bb.length) {
					raise_log("Write Succesful");
				} else {
					raise_log("Write failed, result = "+writeresult);
				}
				
				return writeresult;
			}
		}
		return 0;
	}
	
	/**
	 * Read bytes
	 * @param readcount : bytes to read
	 * @return null if failed
	 */
	public byte[] Read(int readcount) {
		if (opened) {
			if (spi_handle>=0) {
				byte[] result = new byte[readcount];
				int readresult = jGPIO.libC.read(spi_handle, result, readcount);
				if (readresult == readcount) {
					raise_log("Read succesful");
				} else {
					raise_log("Read failed, result="+readresult);
				}
				return result;
			}
		}
		return null;
	}
	
	/**
	 * Check if BUS opened
	 * @return true if opened
	 */
	public boolean IsOpened() {
		return opened;
	}
	
	/**
	 * Get SPI Handle
	 * @return -1 if closed
	 */
	public int SPI_Handle() {
		return spi_handle;
	}
	
	private void raise_log(String msg) {
		if (javaevent!=null) {
			javaevent.Log(msg);
		}
	}
	
	
}
