package SBC;

import anywheresoftware.b4a.BA;
import anywheresoftware.b4a.keywords.DateTime;
import anywheresoftware.b4a.objects.collections.Map;

@BA.ShortName("NetworkMeterInfo")
public class NetworkMeterInfo {
	public final String InterfaceName;
	public final long ticktime;
	public final long Total_RX_Bytes;
	public final long Total_TX_Bytes;
	public final long Total_RX_Packets;
	public final long Total_TX_Packets;
	private boolean isvalid = false;
	
	private long rx_pps = 0;
	private long tx_pps = 0;
	private long rx_bps = 0;
	private long tx_bps = 0;
	public NetworkMeterInfo() {
		InterfaceName="";
		ticktime = DateTime.getNow();
		Total_RX_Bytes = 0;
		Total_TX_Bytes = 0;
		Total_RX_Packets =0;
		Total_TX_Packets = 0;
		isvalid = false;
	}
	public NetworkMeterInfo(String ifname, long tick, long rx_bytes, long tx_bytes, long rx_packets, long tx_packets){
		InterfaceName = ifname;
		ticktime = tick;
		Total_RX_Bytes = rx_bytes;
		Total_TX_Bytes = tx_bytes;
		Total_RX_Packets = rx_packets;
		Total_TX_Packets = tx_packets;
		
		if (!InterfaceName.isEmpty()) {
			if (ticktime>0) {
				if (Total_TX_Bytes>0) {
					if (Total_RX_Bytes>0) {
						if (Total_TX_Packets>0) {
							if (Total_RX_Packets>0) {
								isvalid = true;
							}
						}
					}
				}
			}	
		}
	}
	
	/**
	 * Check if contain valid value
	 * @return true if valid
	 */
	public boolean IsValidValue() {
		return isvalid;
	}
	
	/**
	 * RX Bytes per second
	 * @return value in long
	 */
	public long RX_BytesPerSecond() {
		return rx_bps;
	}
	
	/**
	 * RX Packets per second
	 * @return value in long
	 */
	public long RX_PacketsPerSecond() {
		return rx_pps;
	}
	
	/**
	 * TX Bytes per second
	 * @return value in long
	 */
	public long TX_BytesPerSecond() {
		return tx_bps;
	}
	
	/**
	 * TX Packets per second
	 * @return value in long
	 */
	public long TX_PacketsPerSecond() {
		return tx_pps;
	}

	protected void calculate(NetworkMeterInfo prev) {
		if (prev instanceof NetworkMeterInfo) {
			if (prev.isvalid) {
				rx_pps = Total_RX_Packets - prev.Total_RX_Packets;
				tx_pps = Total_TX_Packets - prev.Total_TX_Packets;
				rx_bps = Total_RX_Bytes - prev.Total_RX_Bytes;
				tx_bps = Total_TX_Bytes - prev.Total_TX_Bytes;
				
				if (rx_pps<1) rx_pps = 0;		// tidak boleh negatif
				if (tx_pps<1) tx_pps = 0;
				if (rx_bps<1) rx_bps = 0;
				if (tx_bps<1) tx_bps = 0;
			}
		}
	}
	
	private final long kp = 1000;
	private final long mp = kp * 1000;
	private final long gp = mp * 1000;
	private final long tp = gp * 1000;
	private final long kb = 1024;
	private final long mb = kb * 1024;
	private final long gb = mb * 1024;
	private final long tb = gb * 1024;
	
	/**
	 * Current Total received packets, in readable string
	 * @return value in string
	 */
	public String Current_RX_PacketTotal() {
		if (this.Total_RX_Packets < kp) {
			return String.valueOf(Total_RX_Packets);
		} else if (Total_RX_Packets < mp) {
			return pembulatan_1_desimal(Total_RX_Packets, kp)+" K";
		} else if (Total_RX_Packets<gp) {
			return pembulatan_1_desimal(Total_RX_Packets, mp)+" M";
		} else if (Total_RX_Packets<tp) {
			return pembulatan_1_desimal(Total_RX_Packets, gp)+" G";
		} else {
			return pembulatan_1_desimal(Total_RX_Packets, tp)+" T";
		}
	}
	
	/**
	 * Current Total transmitted packets, in readable string
	 * @return value in string
	 */
	public String Current_TX_PacketTotal() {
		if (this.Total_TX_Packets < kp) {
			return String.valueOf(Total_TX_Packets);
		} else if (Total_TX_Packets < mp) {
			return pembulatan_1_desimal(Total_TX_Packets, kp)+" K";
		} else if (Total_TX_Packets<gp) {
			return pembulatan_1_desimal(Total_TX_Packets, mp)+" M";
		} else if (Total_TX_Packets<tp) {
			return pembulatan_1_desimal(Total_TX_Packets, gp)+" G";
		} else {
			return pembulatan_1_desimal(Total_TX_Packets, tp)+" T";
		}
	}
	
	/**
	 * Current Total received bytes, in readable string
	 * @return value in string
	 */
	public String Current_RX_ByteTotal() {
		if (this.Total_RX_Bytes < kb) {
			return String.valueOf(Total_RX_Bytes);
		} else if (Total_RX_Bytes < mb) {
			return pembulatan_1_desimal(Total_RX_Bytes, kb)+" K";
		} else if (Total_RX_Bytes<gb) {
			return pembulatan_1_desimal(Total_RX_Bytes, mb)+" M";
		} else if (Total_RX_Bytes<tb) {
			return pembulatan_1_desimal(Total_RX_Bytes, gb)+" G";
		} else {
			return pembulatan_1_desimal(Total_RX_Bytes, tb)+" T";
		}
	}
	
	/**
	 * Current Total transmitted bytes, in readable string
	 * @return value in string
	 */
	public String Current_TX_ByteTotal() {
		if (this.Total_TX_Bytes < kb) {
			return String.valueOf(Total_TX_Bytes);
		} else if (Total_TX_Bytes < mb) {
			return pembulatan_1_desimal(Total_TX_Bytes, kb)+" K";
		} else if (Total_TX_Bytes<gb) {
			return pembulatan_1_desimal(Total_TX_Bytes, mb)+" M";
		} else if (Total_TX_Bytes<tb) {
			return pembulatan_1_desimal(Total_TX_Bytes, gb)+" G";
		} else {
			return pembulatan_1_desimal(Total_TX_Bytes, tb)+" T";
		}
	}
	
	private final long kpps = 1000;
	private final long mpps = kpps * 1000;
	private final long gpps = mpps * 1000;
	private final long kbps = 1024;
	private final long mbps = kbps * 1024;
	private final long gbps = mbps * 1024;
	
	/**
	 * Current RX Packet per second in readable string
	 * @return value in string
	 */
	public String Current_RX_PacketPerSecond() {
		if (rx_pps<kpps) {
			return String.valueOf(rx_pps);
		} else if (rx_pps < mpps) {
			return pembulatan_1_desimal(rx_pps, kpps)+" K";
		} else if (rx_pps < gpps) {
			return pembulatan_1_desimal(rx_pps, mpps)+" M";
		} else {
			return pembulatan_1_desimal(rx_pps, gpps)+" G";
		}
	}
	
	/**
	 * Current TX Packet per second in readable string
	 * @return value in string
	 */
	public String Current_TX_PacketPerSecond() {
		if (tx_pps<kpps) {
			return String.valueOf(tx_pps);
		} else if (tx_pps < mpps) {
			return pembulatan_1_desimal(tx_pps, kpps)+" K";
		} else if (tx_pps < gpps) {
			return pembulatan_1_desimal(tx_pps, mpps)+" M";
		} else {
			return pembulatan_1_desimal(tx_pps, gpps)+" G";
		}
	}
	
	/**
	 * Current RX Bytes per second in readable string
	 * @return value in string
	 */
	public String Current_RX_BytePerSecond() {
		if (rx_bps < kbps) {
			return String.valueOf(rx_bps);
		} else if (rx_bps < mbps) {
			return pembulatan_1_desimal(rx_bps, kbps)+" K";
		} else if (rx_bps < gbps) {
			return pembulatan_1_desimal(rx_bps, mbps)+" M";
		} else {
			return pembulatan_1_desimal(rx_bps, gbps)+" G";
		}
	}
	
	/**
	 * Current TX Bytes per second in readable string
	 * @return value in string
	 */
	public String Current_TX_BytePerSecond() {
		if (tx_bps < kbps) {
			return String.valueOf(tx_bps);
		} else if (tx_bps < mbps) {
			return pembulatan_1_desimal(tx_bps, kbps)+" K";
		} else if (tx_bps < gbps) {
			return pembulatan_1_desimal(tx_bps, mbps)+" M";
		} else {
			return pembulatan_1_desimal(tx_bps, gbps)+" G";
		}
	}
	
	private double pembulatan_1_desimal(long val, long divisor) {
		double vv = (double)val / divisor;
		long ww = (long)(vv * 10);
		return (double)(ww / 10.0);
	}
	
	/**
	 * Complete Summary of this value
	 * @return value in string
	 */
	public String Summary() {
		if (isvalid) {
			StringBuilder str = new StringBuilder();
			str.append("Interface=").append(InterfaceName).append(" ");
			str.append("Date=").append(DateTime.Date(ticktime)).append(" ").append(DateTime.Time(ticktime)).append(" ");
			str.append("RX pps=").append(Current_RX_PacketPerSecond()).append(" bps=").append(Current_RX_BytePerSecond()).append(" ");
			str.append("TX pps=").append(Current_TX_PacketPerSecond()).append(" bps=").append(Current_TX_BytePerSecond());
			return str.toString();
		} else return "";
	}
	
	/**
	 * Create values in JSON Map
	 * @return Map value
	 */
	public Map MakeJsonMap() {
		Map result = new Map();
		result.Initialize();
		result.Put("interface", InterfaceName);
		result.Put("datetimetick", ticktime);
		result.Put("rxbps", rx_bps);
		result.Put("rxpps", rx_pps);
		result.Put("txbps", tx_bps);
		result.Put("txpps", tx_pps);
		result.Put("rxbtotal", this.Total_RX_Bytes);
		result.Put("txbtotal", this.Total_TX_Bytes);
		result.Put("rxptotal", this.Total_RX_Packets);
		result.Put("txptotal", this.Total_TX_Packets);
		result.Put("Crxbps", Current_RX_BytePerSecond());
		result.Put("Crxpps", Current_RX_PacketPerSecond());
		result.Put("Ctxbps", Current_TX_BytePerSecond());
		result.Put("Ctxpps", Current_TX_PacketPerSecond());
		result.Put("Crxpt", Current_RX_PacketTotal());
		result.Put("Ctxpt", Current_TX_PacketTotal());
		result.Put("Crxbt", Current_RX_ByteTotal());
		result.Put("Ctxbt", Current_TX_ByteTotal());
		return result;
	}
}
