package org.openbakery.racecontrol.plugin;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import org.openbakery.jinsim.Car;
import org.openbakery.jinsim.Tiny;
import org.openbakery.jinsim.Track;
import org.openbakery.jinsim.response.ConnectionLeaveResponse;
import org.openbakery.jinsim.response.HiddenMessageResponse;
import org.openbakery.jinsim.response.InSimResponse;
import org.openbakery.jinsim.response.TinyResponse;
import org.openbakery.jinsim.types.InSimTime;
import org.openbakery.racecontrol.Race;
import org.openbakery.racecontrol.data.Driver;
import org.openbakery.racecontrol.data.Lap;
import org.openbakery.racecontrol.event.LapEvent;
import org.openbakery.racecontrol.event.LapEventListener;
import org.openbakery.racecontrol.event.RaceEvent;
import org.openbakery.racecontrol.event.RaceEventListener;
import org.openbakery.racecontrol.gui.Button;
import org.openbakery.racecontrol.gui.Panel;
import org.openbakery.racecontrol.persistence.Persistence;
import org.openbakery.racecontrol.web.bean.MenuItem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Board implements Plugin, LapEventListener, RaceEventListener {
private static Logger log = LoggerFactory.getLogger(Board.class);
private static final int POSITION_Y = 55;
private static final int POSITION_X = 1;
private static final int POSITION_Y_HELP = 90;
private static final int ROWS = 3;
private static final int PERSONAL_BEST_ROW = ROWS + 2;
private static final int SERVER_RECORD_ROW = ROWS + 3;
private HashMap<Integer, Panel> lapTimePanelMap;
private HashMap<Car, Lap> serverBestMap;
private int splits = 4;
private Persistence persistence;
private Track track;
Button recordBy;
private Race race;
public Board(Persistence persistence) {
lapTimePanelMap = new HashMap<Integer, Panel>();
serverBestMap = new HashMap<Car, Lap>();
this.persistence = persistence;
// try {
// JInSimClient.getInstance().send(new TinyRequest(Tiny.SEND_STATE_INFO));
// } catch (IOException e) {
// log.error(e.getMessage(), e);
// }
}
public void packetReceived(InSimResponse response) {
if (response instanceof HiddenMessageResponse) {
HiddenMessageResponse hiddenMessageResonse = (HiddenMessageResponse) response;
if ("board".equalsIgnoreCase(hiddenMessageResonse.getMessage())) {
Driver driver = getDriver(hiddenMessageResonse.getConnectionId());
if (driver != null) {
showStats(driver);
}
}
} else if (response instanceof ConnectionLeaveResponse) {
int connectionId = Integer.valueOf(((ConnectionLeaveResponse) response).getConnectionId());
Panel panel = lapTimePanelMap.get(connectionId);
if (panel != null) {
panel.destroy();
}
lapTimePanelMap.remove(connectionId);
log.debug("remove player: {}", ((ConnectionLeaveResponse) response).getConnectionId());
} else if (response instanceof TinyResponse) {
TinyResponse tinyResponse = (TinyResponse) response;
Tiny type = tinyResponse.getType();
if (type == Tiny.MULTIPLAYER_END || type == Tiny.RACE_END) {
for (Panel panel : lapTimePanelMap.values()) {
panel.destroy();
}
lapTimePanelMap.clear();
}
}
}
private Driver getDriver(int connectionId) {
if (race != null) {
return race.getDriver(connectionId);
}
return null;
}
private void updatePanels() {
if (race != null) {
for (Driver driver : race.getRaceEntry().getDrivers()) {
Panel panel = lapTimePanelMap.get(driver.getConnectionId());
if (panel != null) {
setPanelHeader(panel, driver);
// setBestTimes(driver);
}
}
}
}
private void setPanelHeader(Panel panel, Driver driver) {
int connectionId = driver.getConnectionId();
try {
boolean isVisible = panel.isVisible();
panel.clear();
setPanelColumns(panel);
Button button;
button = new Button(connectionId, "Lap");
panel.add(button, 0, 0);
int i = 1;
for (; i < splits + 1; i++) {
button = new Button(connectionId, "SP" + (i));
panel.add(button, i, 0);
}
button = new Button(connectionId, "Time");
panel.add(button, i++, 0);
button = new Button(connectionId, "Gap");
panel.add(button, i, 0);
panel.setVisible(isVisible);
} catch (IOException e) {
log.error("Visiblity error", e);
}
}
private void setPanelColumns(Panel panel) {
int[] columns = new int[splits + 3];
for (int i = 1; i < columns.length; i++) {
columns[i] = 7;
}
columns[0] = 5;
columns[columns.length - 2] = 10;
panel.setColumns(columns);
}
public void lapSplit(LapEvent event) {
Driver driver = event.getDriver();
int connectionId = driver.getConnectionId();
Panel panel = lapTimePanelMap.get(connectionId);
if (panel != null) {
Lap lap = event.getLap();
if (event.getSplit() == 1) {
// push down the buttons;
for (int y = ROWS; y > 1; y--) {
Lap lapCurrent = getLap(connectionId, y - 1);
Lap lapPrevious = getLap(connectionId, y);
setLapInRow(connectionId, y, lapCurrent, lapPrevious);
}
}
setLapInRow(connectionId, 1, lap, null);
}
}
public void lapFinished(LapEvent event) {
Driver driver = event.getDriver();
Lap lap = event.getLap();
Lap lapPrevious = getLap(driver.getConnectionId(), 2);
setLapInRow(driver.getConnectionId(), 1, lap, lapPrevious);
// updateBestTimes(driver, lap);
}
private void addNewPlayer(Driver driver) {
log.debug("add new player with connectionId: {}", driver);
if (!lapTimePanelMap.containsKey(driver.getConnectionId())) {
Panel panel = new Panel(POSITION_X, POSITION_Y);
lapTimePanelMap.put(driver.getConnectionId(), panel);
setPanelHeader(panel, driver);
}
}
private void showStats(Driver driver) {
log.debug("display board for {}", driver);
if (!lapTimePanelMap.containsKey(driver.getConnectionId())) {
addNewPlayer(driver);
}
Panel panel = lapTimePanelMap.get(driver.getConnectionId());
try {
panel.setVisible(!panel.isVisible());
// if (recordBy != null) {
// recordBy.setVisible(panel.isVisible());
// }
// if (panel.isVisible()) {
// Button help = new Button(driver.getConnectionId(), "REC: Best lap on server, SPB = Personal best on server", POSITION_X, POSITION_Y_HELP, 60, 5);
// help.setHideTime(5000);
// try {
// help.setVisible(true);
// } catch (IOException e) {
// log.error("Unable to set help visible", e);
// }
// }
} catch (IOException e) {
log.error("Error hiding panel for driver " + driver, e);
}
}
// private void setBestTimes(Driver driver) {
// QueryHelper helper = new QueryHelper(persistence);
//
// /*
// * if (driver.getName() == null) { driver.setName("Brilwing"); }
// */
//
// if (track != null && driver.getName() != null && driver.getCarName() != null) {
// Car car = Car.getCarByName(driver.getCarName());
// Lap serverBest = serverBestMap.get(car);
// if (serverBest == null) {
// serverBest = helper.getFastestLapOnServer(track, car);
// }
// if (serverBest != null) {
// serverBestMap.put(car, serverBest);
// }
//
// Lap lap = helper.getFastestLapOnServerForDriver(track, driver);
// setLapInRow(driver.getConnectionId(), PERSONAL_BEST_ROW, null, null, "SPB", true);
// // updateBestTimes(driver, lap);
// }
// }
// private void updateBestTimes(Driver driver, Lap currentLap) {
//
// int connectionId = driver.getConnectionId();
// if (driver.getCarName() == null) {
// return;
// }
// Car car = Car.getCarByName(driver.getCarName());
// Lap serverBest = serverBestMap.get(car);
// if (serverBest == null || (currentLap != null && serverBest.getTime() > currentLap.getTime())) {
// serverBest = currentLap;
// serverBestMap.put(car, serverBest);
// }
// setLapInRow(connectionId, SERVER_RECORD_ROW, serverBest, currentLap, "REC", true);
// String by = "";
// if (serverBest != null) {
// Driver driverBest = serverBest.getDriver();
// if (driverBest != null) {
// by = "by " + driverBest.getName();
// }
// }
//
// if (recordBy == null) {
// recordBy = new Button(connectionId, by, 6, POSITION_Y + 28, 21, 4);
// recordBy.setTextAlign(TextAlign.left);
// } else {
// recordBy.setText(by);
// }
//
// Lap lap = getLap(connectionId, PERSONAL_BEST_ROW);
// if (lap == null || (currentLap != null && lap.getTime() > currentLap.getTime())) {
// lap = currentLap;
// }
// setLapInRow(connectionId, PERSONAL_BEST_ROW, lap, currentLap, "SPB", true);
// }
private Lap getLap(int connectionId, int row) {
Panel panel = lapTimePanelMap.get(connectionId);
if (panel != null) {
Button button = panel.get(0, row);
if (button != null) {
return (Lap) button.getObject();
}
}
return null;
}
private void setLapInRow(int connectionId, int row, Lap currentLap, Lap previousLap) {
if (currentLap == null) {
setLapInRow(connectionId, row, currentLap, previousLap, "", false);
} else {
setLapInRow(connectionId, row, currentLap, previousLap, Integer.toString(currentLap.getNumber()), false);
}
}
private void setLapInRow(int connectionId, int row, Lap currentLap, Lap previousLap, String label, boolean inverseGap) {
Panel panel = lapTimePanelMap.get(connectionId);
if (panel == null) {
return;
}
Button button = panel.get(0, row);
if (label == null) {
label = "";
}
if (button != null) {
button.setText(label);
} else {
button = new Button(connectionId, label);
panel.add(button, 0, row);
}
button.setObject(currentLap);
for (int i = 0; i < splits; i++) {
String split = "";
if (currentLap != null && currentLap.getSplit(i) > 0) {
split = InSimTime.toString(currentLap.getSplit(i));
}
button = panel.get(i + 1, row);
if (button != null) {
button.setText(split);
} else {
button = new Button(connectionId, split);
panel.add(button, i + 1, row);
}
}
button = panel.get(splits + 1, row);
String time = "";
if (currentLap != null && currentLap.getTime() > 0) {
time = InSimTime.toString(currentLap.getTime());
}
if (button != null) {
button.setText(time);
} else {
button = new Button(connectionId, time);
panel.add(button, splits + 1, row);
}
String gap = "";
if (previousLap != null && currentLap != null && previousLap.getTime() > 0 && currentLap.getTime() > 0) {
if (inverseGap) {
gap = InSimTime.toString(currentLap.getTime() - previousLap.getTime(), true);
} else {
gap = InSimTime.toString(previousLap.getTime() - currentLap.getTime(), true);
}
}
button = panel.get(splits + 2, row);
if (button != null) {
button.setText(gap);
} else {
button = new Button(connectionId, gap);
panel.add(button, splits + 2, row);
}
}
public String getHelp() {
return "Displays the last 3 lap times";
}
public String getName() {
return "Board";
}
public void raceEndEvent(RaceEvent event) {
this.race = null;
}
public void raceStartEvent(RaceEvent event) {
track = Track.getTrackByShortName(event.getRace().getRaceEntry().getTrack());
splits = track.getSplits();
this.race = event.getRace();
updatePanels();
}
public void raceNewDriverEvent(RaceEvent event) {
addNewPlayer(event.getDriver());
// setBestTimes(event.getDriver());
}
public List<MenuItem> getMenuItems() {
return Collections.emptyList();
}
}