package addon.stopwatch;
import bashoid.Message;
import bashoid.Addon;
import java.util.ArrayList;
import java.util.Iterator;
import static utils.Constants.*;
public class Stopwatch extends Addon {
private enum Cmds {
CMD_INVALID, CMD_START_STOPWATCH, CMD_STOP_STOPWATCH, CMD_GET_STOPWATCH, CMD_SET_TIMER , CMD_REMOVE_TIMER;
};
private static final short HOUR = 3600;
private static final short MINUTE = 60;
private long stopwatchTime;
private boolean stopwatchRunning;
private String stopwatchAuthor;
private ArrayList<StopwatchTimer> timers = new ArrayList<>();
public Stopwatch() {
stopwatchRunning = false;
}
private String executeCmd(Cmds cmd, String message, String author) {
switch(cmd) {
case CMD_START_STOPWATCH:
if(stopwatchRunning)
return "Stopwatch is already running";
stopwatchRunning = true;
stopwatchTime = 0;
stopwatchAuthor = author;
startUpdate();
return "Stopwatch started";
case CMD_STOP_STOPWATCH:
{
if(!stopwatchRunning)
return "Stopwatch is not running";
if(!stopwatchAuthor.equals(author))
return "You can't stop " + stopwatchAuthor + "'s stopwatch";
stopwatchRunning = false;
stopUpdate();
String result = "Stopwatch stopped at " + timeToString(stopwatchTime);
stopwatchTime = 0;
return result;
}
case CMD_GET_STOPWATCH:
{
if(!stopwatchRunning)
return "Stopwatch is not running";
String result = "Stopwatch is at " + timeToString(stopwatchTime);
return result;
}
case CMD_SET_TIMER:
{
for(StopwatchTimer t : timers) {
if(author.equals(t.getAuth()))
return "You already have one timer";
}
int index = message.indexOf(' ');
if(index == NOT_FOUND)
return "You need to set time";
index = message.indexOf(' ', index+1)+1;
long time = parseTime(message, index);
if(time == 0)
return "You need to set time in correct form (eg. 4h10m5s)";
long period = MINUTE;
index = message.indexOf(' ', index);
if(index != NOT_FOUND)
period = parseTime(message, index+1);
StopwatchTimer timer = new StopwatchTimer(author, time, period);
timers.add(timer);
startUpdate();
return "Timer for " + time + " seconds started for " + author;
}
case CMD_REMOVE_TIMER:
{
StopwatchTimer tm = null;
Iterator<StopwatchTimer> it = timers.iterator();
while ( it.hasNext() ) {
StopwatchTimer t = it.next();
if(author.equals(t.getAuth())) {
tm = t;
it.remove();
}
}
if(tm == null)
return "You don't have timer";
stopUpdate();
return author + "'s timer for " + timeToString(tm.getBaseTime()) + " removed";
}
}
return null;
}
private void startUpdate() {
if(periodicAddonUpdate == null)
setPeriodicUpdate(1000);
}
private void stopUpdate() {
if(periodicAddonUpdate != null && !stopwatchRunning && timers.size() == 0)
stopPeriodicUpdate();
}
public static String timeToString(long time) {
String result = "";
if(time < MINUTE)
result += time + "s";
else {
if(time/MINUTE < MINUTE) {
result += (long)Math.floor(time/MINUTE) + "m";
if(dv(time,MINUTE) != 0)
result += " " + dv(time,MINUTE) + "s";
} else {
result += (long)Math.floor(time/HOUR) + "h";
if(dv(time,HOUR) >= MINUTE)
result += " " + (long)Math.floor(dv(time,3600)/MINUTE) + "m";
if(dv(time,MINUTE) != 0)
result += " " + dv(time,MINUTE) + "s";
}
}
return result;
}
private long parseTime(String message, int index) {
long result = 0;
int end = message.indexOf(' ', index);
if(end == NOT_FOUND)
end = message.length();
String time = message.substring(index, end).toLowerCase();
try{
result = Integer.decode(time);
return result;
}
catch(Exception e){ }
String tmp = "";
char ch;
for(byte i = 0; i < time.length(); ++i) {
ch = time.charAt(i);
if(tmp.length() != 0) {
short mul = NOT_FOUND;
if (ch == 'h') mul = HOUR;
else if(ch == 'm') mul = MINUTE;
else if(ch == 's') mul = 1;
if(mul != NOT_FOUND) {
try{
result += Integer.decode(tmp)*mul;
}
catch(Exception e){
return 0;
}
tmp = "";
continue;
}
}
tmp += ch;
}
return result < 0 ? 0 : result;
}
public static long dv(long num, long div) {
return num - ((long)Math.floor(num/div)*div);
}
private Cmds getCommand(String message) {
int begin = message.indexOf(' ') + 1;
int end = message.indexOf(' ', begin);
if(end == NOT_FOUND)
end = message.length();
String cmd = message.substring(begin, end);
if(cmd.equals("start"))
return Cmds.CMD_START_STOPWATCH;
else if(cmd.equals("stop"))
return Cmds.CMD_STOP_STOPWATCH;
else if(cmd.equals("get"))
return Cmds.CMD_GET_STOPWATCH;
else if(cmd.equals("timer")) {
begin = message.indexOf(' ', end);
if(begin == NOT_FOUND)
return Cmds.CMD_INVALID;
return Cmds.CMD_SET_TIMER;
}
else if(cmd.equals("rmtimer"))
return Cmds.CMD_REMOVE_TIMER;
return Cmds.CMD_INVALID;
}
@Override
public boolean shouldReact(Message message) {
return message.text.startsWith("stopwatch") && message.text.indexOf(' ') != NOT_FOUND;
}
@Override
protected void setReaction(Message message) {
Cmds cmd = getCommand(message.text);
if(cmd == Cmds.CMD_INVALID)
return;
String result = executeCmd(cmd, message.text, message.author);
if(result != null)
reaction.add(result);
}
@Override
public void periodicAddonUpdate() {
if(stopwatchRunning)
++stopwatchTime;
Iterator<StopwatchTimer> it = timers.iterator();
while ( it.hasNext() ) {
StopwatchTimer t = it.next();
if(!t.update()) {
it.remove();
stopUpdate();
}
if(t.getResponse() != null)
sendMessage(t.getAuth(), t.getResponse());
}
}
}