package devices;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;

import anywheresoftware.b4a.BA;
import anywheresoftware.b4a.keywords.Regex;

@BA.ShortName("PublicIPChecker")
@BA.Events(values= {
		"log(msg as string)",
		"publicip(success as boolean, testserver as string, result as string)"
})


// https://stackoverflow.com/questions/2939218/getting-the-external-ip-address-in-java

public class PublicIPChecker {

	private final String[] servers = {
			"http://checkip.amazonaws.com/",
			"https://ipv4.icanhazip.com/",
			"http://myexternalip.com/raw",
			"http://ipecho.net/plain",
			"http://bot.whatismyipaddress.com"
	};
	
	private final String regex_validip = "^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$";
	
	private BA bax;
	private Object caller;
	private String event="";
	private final Object Me = this;
	private boolean need_log_event = false;
	private boolean need_publicip_event = false;
	
	/**
	 * Initialize Public IP Checker
	 * @param callerobject : callback object
	 * @param eventname : eventname
	 */
	public void Initialize(BA ba, Object callerobject, String eventname) {
		bax = ba;
		caller = callerobject;
		event = eventname;
		if (bax instanceof BA) {
			if (caller != null) {
				if (!event.isEmpty()) {
					need_log_event = bax.subExists(event+"_log");
					need_publicip_event = bax.subExists(event+"_publicip");
				}
			}
		}
	}
	
	/**
	 * Get Public IP
	 * Will raise event publicip(success as boolean, testserver as string, result as string)
	 */
	public void GetPublicIP() {
		Thread tx = new Thread(new Runnable() {

			@Override
			public void run() {
				boolean success = false;
				String currentserver = "";
				String resultip = "";
				for(int ii=0;ii<servers.length;ii++) {
					currentserver = servers[ii];
					
					try {
						URL testserver= new URL(currentserver);
						BufferedReader in = new BufferedReader(new InputStreamReader(testserver.openStream()));
						String ip = in.readLine();
						if (!ip.isEmpty()) {
							
							if (Regex.IsMatch(regex_validip, ip)) {
								resultip = ip;
								success = true;
								raise_log("Public IP = "+resultip+", obtained from "+currentserver);
								break;
							} else raise_log("Result="+ip+" from "+currentserver+" is not valid IP format");
						} else raise_log("Empty result from "+currentserver+", will try another server");
					} catch (MalformedURLException e) {
						raise_log("Invalid ServerURL : "+currentserver);
						continue;
					} catch (IOException e) {
						raise_log("Unable to read from ServerURL : "+currentserver);
						continue;
					}
					
				}
				
				raise_publicip(success, currentserver, resultip);
			}
			
		});
		tx.start();
	}
	
	
	
	
	private void raise_log(String value) {
		if (need_log_event) bax.raiseEventFromDifferentThread(Me, null, 0, event+"_log", false, new Object[] {value});
	}
	
	private void raise_publicip(boolean success, String servertotest, String result) {
		if (need_publicip_event) bax.raiseEventFromDifferentThread(Me, null, 0, event+"_publicip", false, new Object[] {success, servertotest, result});
	}
	
}
