import java.net.ServerSocket;
import java.net.Socket;
import java.io.IOException;

public class Server {

    private ServerSocket serverSocket;

    
    public Server(ServerSocket _Socket) {
        this.serverSocket = _Socket;
    }

    //Method to make the server start
    public void startServer() {

        //Applying try block allows definition of a block of code to be tested for errors while it is running until the server socket shutdown.
        try {

            while (!serverSocket.isClosed()) { //while serverSocket is constantly running //While client is in waiting

                //Declare Socket object 
                Socket socket = serverSocket.accept(); //accept method is used. The server won't run until a client has connected
                System.out.println("Server INFO: Someone has connected!");
                //ClientHandler declared as clienthandler as this class extends thread and socket
                //ClientHandler object is used to send and receive msg with the client in the same server.
                ClientHandler clientHandler = new ClientHandler(socket); //constructor socket is used from the accept method

                // New Threads provide a way for a program to perform multiple tasks at the same time
                Thread thread = new Thread(clientHandler);
                thread.start(); //Start to run the Thread method

                //A thread is a sequential flow of instructions in the program that can be executed independently.
                //When the program is running, the the thread is in process. Multiple threads can run at the same time and perform different tasks while in the same program

            }

        } catch (IOException e) { 
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(9999); //Server will listen for clients that are connecting to the Port No. if it matches
        Server server = new Server(serverSocket);
        server.startServer(); //called method for the startServer
    }

    //if an error occurs in the try block and to avoid nested catches 
    public void closeSocket() {
        try {
            if (serverSocket != null) {
                serverSocket.close();
            }
        } catch (IOException e) {
            e.printStackTrace(); //method to handle errors and exceptions
        }
    }
}
