package vs;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;

/**
 * iterative server for var.sockets.tcp.filer File service. waits for the next
 * client to connect. Upon connection sends a manually defined file back to
 * client. closes the connection directly afterwards and handles then next
 * client
 *
 * @author Sandro Leuchter
 *
 */
public class FileServerIterativ {
	/**
	 * path to file which will be sent to clients; relative to current working
	 * directory (e.g. project root)
	 */
	private static final String FILE = "target/classes/message.txt";
	/**
	 * port on which this service is currently listening on localhost
	 */
	private final int port;
	/**
	 * requested maximum length of the queue of incoming connections.
	 */
	private final int backlog;

	/**
	 * the only constructor for this class
	 *
	 * @param port    port on which this service will be listening on localhost
	 * @param backlog requested maximum length of the queue of incoming connections.
	 */
	public FileServerIterativ(int port, int backlog) {
		this.port = port;
		this.backlog = backlog;
	}

	/**
	 * creates server socket on localhost:port, infinitely handles connections to
	 * clients one after another
	 */
	public void start() {
		try (ServerSocket serverSocket = new ServerSocket(this.port, this.backlog)) {
			System.out.println("FileServer (iterativ) auf " + serverSocket.getLocalSocketAddress() + " gestartet ...");
			File file = new File(FILE);
			if (file.exists()) {
				System.out.println("\"" + file.getAbsolutePath() + "\" soll gesendet werden.");
				while (true) {
					handleClient(serverSocket);
				}
			}
		} catch (IOException e) {
			System.err.println(e);
		}
	}

	/**
	 * waits for the next client to connect. Upon connection sends a manually
	 * defined file back to client. closes the connection directly afterwards and
	 * handles then next client
	 *
	 * @param server "welcome socket" on which server is listening for clients
	 */
	private void handleClient(ServerSocket server) {
		SocketAddress socketAddress = null;
		try (Socket socket = server.accept();
				BufferedReader in = new BufferedReader(new FileReader(FILE));
				PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) {
			socketAddress = socket.getRemoteSocketAddress();
			System.out.println("Verbindung zu  " + socketAddress + " aufgebaut");
			// Inhalt von in zeilenweise an out senden:
			System.out.println("Übertragung zu " + socketAddress + " begonnen");
			String input;
			while ((input = in.readLine()) != null) {
				out.println(input);
			}
			System.out.println("Übertragung zu " + socketAddress + " beendet");
		} catch (IOException e) {
			System.err.println(e);
		} finally {
			System.out.println("Verbindung zu  " + socketAddress + " abgebaut");
		}
	}

	/**
	 * main method: entrypoint to run service
	 *
	 * @param args args[0] must be the port number of the server (int); rest of args
	 *             is ignored
	 */
	public static void main(String[] args) {
		int port = Integer.parseInt(args[0]);
		int backlog = 50;
		if (args.length == 2) {
			backlog = Integer.parseInt(args[1]);
		}

		new FileServerIterativ(port, backlog).start();
	}
}
