package dev.llan.model;
import dev.llan.model.board.Point;
import dev.llan.events.GameEvent;
import dev.llan.events.GameInitializedEvent;
import dev.llan.model.cards.Card;
import dev.llan.receivers.Receiver;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static dev.llan.model.Constants.*;
public final class GameContainer implements Model {
private static GameContainer instance;
public static GameContainer getInstance() {
if (instance == null) {
instance = new GameContainer();
}
return instance;
}
private final ExecutorService backgroundThread = Executors.newSingleThreadExecutor();
private Game game;
private final EventManager eventManager;
private GameContainer() {
eventManager = new EventManager();
}
@Override
public Game initGame() {
try {
return backgroundThread
.submit(
() -> {
try {
game = new Game(GAME_SIZE);
broadcastEvents(List.of(new GameInitializedEvent()));
return game;
} catch (RuntimeException e) {
e.printStackTrace();
throw e;
}
})
.get();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public Game getCurrentGame() {
return game;
}
@Override
public void registerReceiver(Receiver receiver) {
eventManager.registerReceiver(receiver);
}
@Override
public void removeReceiver(Receiver receiver) {
eventManager.removeReceiver(receiver);
}
@Override
public void tryMoveTo(Point position) {
backgroundThread.submit(
() -> {
try {
List<GameEvent> events = game.tryMoveTo(position);
broadcastEvents(events);
} catch (RuntimeException e) {
e.printStackTrace();
}
});
}
@Override
public void moveActivePath() {
backgroundThread.submit(
() -> {
try {
List<GameEvent> events = game.moveActivePath();
broadcastEvents(events);
} catch (RuntimeException e) {
e.printStackTrace();
}
});
}
@Override
public void endTurn() {
backgroundThread.submit(
() -> {
try {
List<GameEvent> events = game.endTurn();
broadcastEvents(events);
} catch (RuntimeException e) {
e.printStackTrace();
}
});
}
@Override
public void waitTurn() {
backgroundThread.submit(
() -> {
try {
List<GameEvent> events = game.waitTurn();
broadcastEvents(events);
} catch (RuntimeException e) {
e.printStackTrace();
}
});
}
@Override
public void useCardOn(Point position) {
backgroundThread.submit(
() -> {
try {
List<GameEvent> events = game.useCardOn(position);
broadcastEvents(events);
} catch (RuntimeException e) {
e.printStackTrace();
}
});
}
@Override
public void swapCards(int first, int second) {
backgroundThread.submit(
() -> {
try {
List<GameEvent> events = game.swapCards(first, second);
broadcastEvents(events);
} catch (RuntimeException e) {
e.printStackTrace();
}
});
}
@Override
public Optional<Card> selectCard(int cardIndex) {
try {
return backgroundThread
.submit(
() -> {
try {
List<GameEvent> events = game.selectCard(cardIndex);
broadcastEvents(events);
return game.getPlayer().getSelectedCard();
} catch (RuntimeException e) {
e.printStackTrace();
throw e;
}
})
.get();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public void removeCard(int index) {
backgroundThread.submit(
() -> {
try {
List<GameEvent> events = game.removeCard(index);
broadcastEvents(events);
} catch (RuntimeException e) {
e.printStackTrace();
}
});
}
@Override
public void equip(int index) {
backgroundThread.submit(
() -> {
try {
List<GameEvent> events = game.equip(index);
broadcastEvents(events);
} catch (RuntimeException e) {
e.printStackTrace();
}
});
}
@Override
public void swapEquipment(int first, int second) {
backgroundThread.submit(
() -> {
try {
List<GameEvent> events = game.swapEquipment(first, second);
broadcastEvents(events);
} catch (RuntimeException e) {
e.printStackTrace();
}
});
}
@Override
public void removeEquipment(int index) {
backgroundThread.submit(
() -> {
try {
List<GameEvent> events = game.removeEquipment(index);
broadcastEvents(events);
} catch (RuntimeException e) {
e.printStackTrace();
}
});
}
@Override
public void setHighlighted(Point point, boolean highlighted) {
backgroundThread.submit(
() -> {
try {
List<GameEvent> events = game.setHighlighted(point, highlighted);
broadcastEvents(events);
} catch (RuntimeException e) {
e.printStackTrace();
}
});
}
@Override
public boolean isInRange(Point point) {
return game.getPlayer().isInRange(point);
}
private void broadcastEvents(List<GameEvent> events) {
if (events.size() > 1) {
events.getFirst().setDisableControls(true);
events.getLast().setEnableControls(true);
}
for (GameEvent event : events) {
eventManager.broadcast(event);
}
}
}