package org.fhnw.aigs.TicTacToe.client;
import javafx.event.EventHandler;
import javafx.scene.input.MouseEvent;
import org.fhnw.aigs.client.GUI.BaseBoard;
import org.fhnw.aigs.client.gameHandling.ClientGame;
import org.fhnw.aigs.commons.FieldStatus;
import org.fhnw.aigs.commons.communication.FieldClickFeedbackMessage;
import org.fhnw.aigs.commons.communication.FieldClickMessage;
import org.fhnw.aigs.commons.communication.Message;
// -- References to internal packages (of this game)
import org.fhnw.aigs.TicTacToe.commons.TicTacToeFieldChangedMessage;
import org.fhnw.aigs.TicTacToe.commons.TicTacToeSymbol;
/**
* This is the class representing the TicTacToe board.
* It contains 3 x 3 TicTacToePanes.
* All event handlers and animations as well as the creation of the TicTacToePanes
* occurs here.<br>
* v1.0 Initial release<br>
* v1.0.1 Minor changes
* @author Matthias Stöckli (v1.0)
* @version v1.0.1
*/
public class TicTacToeBoard extends BaseBoard{
public TicTacToeBoard(int x, int y, ClientGame clientGame){
super(x, y, clientGame);
this.setFields(); // Define the appearance of the board and the fields
this.setEventHandlers(); // Set the event handlers, i.e. how the GUI will react
}
/**
* Sets the field appearance of the TicTacToeFields.
* In this case it is sufficient to iterate through the x and y axis
* and create a new TicTacToeField for every field. Then this new field
* is added to the TicTacToeBoard. <br>
*/
@Override
public void setFields(){
for(int i = 0; i < fieldsX; i++){
for(int j = 0; j < fieldsY; j++){
TicTacToePane ticTacToePane = new TicTacToePane();
fieldPanes[i][j] = ticTacToePane;
this.add(ticTacToePane, i, j);
}
}
}
/**
* This method wires the TicTacToeFields to their respective actions.
* Whenever one of the fields is clicked, a FieldClickedMessage will be sent
* which is based upon the clicked field. The server will then react.
*/
@Override
public void setEventHandlers(){
// Go through all fields
for(int i = 0; i < this.getFieldsX(); i++){
for(int j = 0; j < this.getFieldsY(); j++){
// Set an anonymous event handler which reacts on clicks
this.getField(i, j).setOnMouseClicked(
new EventHandler<MouseEvent>(){
@Override
public void handle(MouseEvent event) {
TicTacToePane sourceField = (TicTacToePane)event.getSource(); // Get the source, i.e. which field was clicked
int xPosition = getColumnIndex(sourceField); // Get the column
int yPosition = getRowIndex(sourceField); // Get the row
// Create a field click message based on the coordinates
FieldClickMessage fieldClickMessage = new FieldClickMessage(xPosition, yPosition);
clientGame.sendMessageToServer(fieldClickMessage);
}});
}
}
}
/**
* This method is responsible for any UI changes.
* @param message
*/
@Override
public void manipulateGUI(Message message){
if(message instanceof TicTacToeFieldChangedMessage){
changeField((TicTacToeFieldChangedMessage)message);
}
else if(message instanceof FieldClickFeedbackMessage){
provideFeedback((FieldClickFeedbackMessage)message);
}
}
/**
* Changes the field according to the TicTacToeFieldChangedMessage sent by the
* server.
* @param fieldChangedMessage The message sent by the server.
*/
private void changeField(TicTacToeFieldChangedMessage fieldChangedMessage) {
int x = fieldChangedMessage.getXPosition();
int y = fieldChangedMessage.getYPosition();
TicTacToePane changedField = (TicTacToePane)this.getField(x, y);
TicTacToeSymbol playerSymbol = fieldChangedMessage.getPlayerSymbol();
changedField.setPlayerSymbol(playerSymbol);
}
/**
* Provides a feedback based on the feedback message sent by the server.
* @param fieldClickFeedbackMessage The message which indicates which field was clicked
*/
private void provideFeedback(FieldClickFeedbackMessage fieldClickFeedbackMessage) {
int x = fieldClickFeedbackMessage.getxPosition();
int y = fieldClickFeedbackMessage.getyPosition();
TicTacToePane changedField = (TicTacToePane)this.getField(x, y);
if(fieldClickFeedbackMessage.getFieldStatus() == FieldStatus.Blocked || fieldClickFeedbackMessage.getFieldStatus() == FieldStatus.NoChange ){
changedField.playBusyAnimation();
}
}
}