package netgame.tictactoe;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.control.RadioButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.control.Alert;
import javafx.scene.layout.VBox;
import javafx.scene.layout.HBox;
import javafx.scene.layout.BorderPane;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.geometry.Pos;
import javafx.geometry.Insets;

import java.io.IOException;
import netgame.common.*;


/**
 *  A main class for the network TicTacToe game.  This program
 *  shows a primary window where the user can choose to be a server or
 *  a client.  If the user chooses to be a server, then a TicTacToeHub
 *  is created to manage the game; the game will not start until a
 *  second player has connected as a client.  To act as a client,
 *  the user must know the host name or IP address of the computer
 *  and the port number where the server is waiting for a connection.
 *  When run as a client, this program does not create a hub;
 *  rather, it connects to the hub that was created by the server.
 *  In either case, a TicTacToeWindow is created where the game will 
 *  be played.
 */
public class Main extends Application {

    private static final int DEFAULT_PORT = 45017;
    
    public static void main(String[] args) {
        launch(args);
    }
    //------------------------------------------------------------------------------
    
    private Stage window;  // The first window that shows on the screen, with connection controls.
    
    private Label message;
    private TextField listeningPortInput;
    private TextField hostInput;
    private TextField connectPortInput;
    
    public void start(Stage stage) {
        
        window = stage;
        
        Button okButton = new Button("OK");
        okButton.setDefaultButton(true);
        Button cancelButton = new Button("Cancel");
        cancelButton.setCancelButton(true);
        
        message = new Label("Welcome to Networked TicTacToe!");
        message.setFont(Font.font("Times New Roman", FontWeight.BOLD, 24));
        
        listeningPortInput = new TextField("" + DEFAULT_PORT);
        listeningPortInput.setPrefColumnCount(5);
        hostInput = new TextField();
        hostInput.setPrefColumnCount(30);
        connectPortInput = new TextField("" + DEFAULT_PORT);
        connectPortInput.setPrefColumnCount(5);
        
        RadioButton selectServerMode = new RadioButton("Start a new game");
        selectServerMode.setFont(Font.font("Arial", FontWeight.BOLD, 14));
        RadioButton selectClientMode = new RadioButton("Connect to existing game");
        selectClientMode.setFont(Font.font("Arial", FontWeight.BOLD, 14));
        
        ToggleGroup group = new ToggleGroup();
        selectServerMode.setToggleGroup(group);
        selectClientMode.setToggleGroup(group);
        
        Label listenPortLabel = new Label("Listen On Port: ");
        listenPortLabel.setFont(Font.font("Arial", FontWeight.BOLD, 14));
        Label hostLabel = new Label("Computer: ");
        hostLabel.setFont(Font.font("Arial", FontWeight.BOLD, 14));
        Label connectPortLabel = new Label("Port Number: ");
        connectPortLabel.setFont(Font.font("Arial", FontWeight.BOLD, 14));
        
        HBox row2 = new HBox(listenPortLabel,listeningPortInput);
        HBox row4 = new HBox(hostLabel,hostInput);
        HBox row5 = new HBox(connectPortLabel,connectPortInput);
        
        VBox inputs = new VBox(15,message,selectServerMode,row2,selectClientMode,row4,row5);
        VBox.setMargin(row2, new Insets(0,0,0,50));
        VBox.setMargin(row4, new Insets(0,0,0,50));
        VBox.setMargin(row5, new Insets(0,0,0,50));
        inputs.setStyle("-fx-padding:20px; -fx-border-color:black; -fx-border-width:2px");
        HBox bottom = new HBox(8,cancelButton,okButton);
        bottom.setPadding(new Insets(10,0,0,0));
        bottom.setAlignment(Pos.CENTER);
        BorderPane root = new BorderPane();
        root.setCenter(inputs);
        root.setBottom(bottom);
        root.setPadding( new Insets(15,15,10,15) );
    
        stage.setScene( new Scene(root) );
        stage.setTitle("Net TicTacToe");
        stage.setResizable(false);
        
        cancelButton.setOnAction( e -> Platform.exit() );
        okButton.setOnAction( e -> doOK( selectServerMode.isSelected() ) );

        selectServerMode.setOnAction( e -> {
            listeningPortInput.setDisable(false);
            hostInput.setDisable(true);
            connectPortInput.setDisable(true);
            listeningPortInput.setEditable(true);
            hostInput.setEditable(false);
            connectPortInput.setEditable(false);
        });
        selectClientMode.setOnAction( e -> {
            listeningPortInput.setDisable(true);
            hostInput.setDisable(false);
            connectPortInput.setDisable(false);
            listeningPortInput.setEditable(false);
            hostInput.setEditable(true);
            connectPortInput.setEditable(true);
        });
        
        selectServerMode.setSelected(true);
        hostInput.setDisable(true);
        connectPortInput.setDisable(true);
        hostInput.setEditable(false);
        connectPortInput.setEditable(false);
        
        stage.show();
        
    } // end start()

    
    private void errorMessage(String message) {
        Alert alert = new Alert(Alert.AlertType.ERROR, message);
        alert.showAndWait();
    }
    
    
    private void doOK( boolean openAsServer) {
        // If the user has choosen to run as the server, then a TicTacToeGameHub (server) 
        // is created and after that a TicTacToeWindow is created that connects to the new
        // server running on  localhost.  In that case, the game will wait for a second 
        // connection. 
        //    If the user chooses to connect to an existing server, then only
        // a TicTacToeWindow is created, which will connect to the specified
        // host where the server is running.
        
        if (openAsServer) {
            int port;
            try {
                port = Integer.parseInt(listeningPortInput.getText().trim());
                if (port <= 0)
                    throw new Exception();
            }
            catch (Exception e) {
                errorMessage("The value in the \"Listen on port\" box\nis not a legal positive integer!");
                message.setText("Illegal port number.  Please try again!");
                listeningPortInput.selectAll();
                listeningPortInput.requestFocus();
                return;
            }
            Hub hub;
            try {
                hub = new TicTacToeGameHub(port);
            }
            catch (Exception e) {
                errorMessage("Sorry, could not listen on port number " + port);
                message.setText("Please try a different port number!");
                listeningPortInput.selectAll();
                listeningPortInput.requestFocus();
                return;
            }
            new TicTacToeWindow("localhost", port);
            window.hide();
        }
        else {
            String host;
            int port;
            host = hostInput.getText().trim();
            if (host.length() == 0) {
                errorMessage("You must enter the name or IP address\nof the computer that is hosting the game.");
                message.setText("You must enter a computer name!");
                hostInput.requestFocus();
                return;
            }
            try {
                port = Integer.parseInt(connectPortInput.getText().trim());
                if (port <= 0)
                    throw new Exception();
            }
            catch (Exception e) {
                errorMessage("The value in the \"Port Number\" box\nis not a legal positive integer!");
                message.setText("Illegal port number.  Please try again!");
                connectPortInput.selectAll();
                connectPortInput.requestFocus();
                return;
            }
            new TicTacToeWindow(host,port);
            window.hide();
        }
        
    } // end doOK
            
        
} // end TicTacToe Main
