package devices;

import anywheresoftware.b4a.BA;
import jGPIO.jGPIO;
import jGPIO.DigitalOutput.DigitalOutput;

@BA.ShortName("buzzer")

/***
 * Buzzer class
 * use class DigitalOutput
 * @author rdkartono
 *
 */
public class Buzzer {
	private DigitalOutput dox;
	private int mypinnumber;
	private BA ba;
	private boolean initialized = false;
	private boolean continuebuzzing = false;
	private boolean activelow = false;
	
	public Buzzer() {
		if (jGPIO.osname=="") jGPIO.detectOS();
	}
	/**
	 * Initialize buzzer Object
	 * @param pin_number : pin number connected to buzzer
	 * @param activelow : if true, logic low will turn ON buzzer, logic high will turn OFF buzzer
	 * @return true if Initialized
	 */
	public boolean Initialize(BA bax, int pin_number, boolean activelow) {
		this.mypinnumber = pin_number;
		this.ba = bax;
		this.activelow = activelow;
		initialized = false;
		if (jGPIO.IsLinux==false) {
			return false;
		}
		
		dox = new DigitalOutput();
		dox.Initialize(this.ba, null, "digitalout", mypinnumber, false);
		initialized = dox.getIsInitialized();
		
		 Runtime.getRuntime().addShutdownHook(new Thread() {
	            @Override
	            public void run() {
	                CloseBuzzer();
	            }
	        });
		 
		return initialized;
	}
	
	/**
	 * Check if Initialzied
	 * @return true if already initialized
	 */
	public boolean getIsInitialized() {
		return initialized;
	}
	
	/**
	 * Stop buzzing
	 */
	public void Stop_Buzzing() {
		continuebuzzing = false;
	}
	
	/**
	 * Start continuous buzzing
	 */
	public void Start_Continuous_Buzzing() {
		
		Thread tx = new Thread() {
			public void run() {
				if (digitaloutputready())
					if (activelow)				// turn ON
						dox.SetLow();
					else
						dox.SetHigh();			
				else
					return;					// digital output not ready
				
				continuebuzzing = true;
				while (continuebuzzing) {
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						break;		// exit while
					}
					
				}
				
				if (digitaloutputready()) 
					if (activelow)				// turn OFF
						dox.SetHigh();
					else
						dox.SetLow();
				
				continuebuzzing = false;
			}
		};
		tx.start();
	}
	
	
	/**
	 * Start pulsing with 1s ON and 2s OFF
	 */
	public void Start_LongPulse_Buzzing() {
		Thread tx = new Thread() {
			public void run() {
				continuebuzzing = true;
				while (continuebuzzing) {
					if (digitaloutputready()) {
						if (activelow)				// turn ON
							dox.SetLow();
						else
							dox.SetHigh();	
					} else {
						break;			// digital output not ready
					}
					
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						break;
					}
					
					if (digitaloutputready()) {
						if (activelow)				// turn OFF
							dox.SetHigh();
						else
							dox.SetLow();
					} else {
						break;		// digital output not ready
					}
					
					try {
						Thread.sleep(2000);
					} catch (InterruptedException e) {
						break;
					}
				}
				continuebuzzing = false;
			}
		};
		tx.start();
	}
	
	/**
	 * Start pulsing with 1s ON and 1s OFF
	 */
	public void Start_MediumPulse_Buzzing() {
		Thread tx = new Thread() {
			public void run() {
				continuebuzzing = true;
				while (continuebuzzing) {
					if (digitaloutputready()) {
						if (activelow)				// turn ON
							dox.SetLow();
						else
							dox.SetHigh();	
					} else {
						break;			// digital output not ready
					}
					
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						break;
					}
					
					if (digitaloutputready()) {
						if (activelow)				// turn OFF
							dox.SetHigh();
						else
							dox.SetLow();
					} else {
						break;		// digital output not ready
					}
					
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						break;
					}
				}
				continuebuzzing = false;
			}
		};
		tx.start();
	}
	
	private boolean digitaloutputready() {
		if (initialized==false) return false;
		if (dox==null) return false;
		return dox.getIsInitialized();
	}
	
	/**
	 * Close buzzer 
	 */
	public void CloseBuzzer() {
		if (dox instanceof DigitalOutput) {
			dox.Release();
			dox = null;
		}
		initialized = false;
	}
	
}
