package com.jenjinstudios.io.server;

import com.jenjinstudios.io.ExecutionContext;
import com.jenjinstudios.io.connection.Connection;
import com.jenjinstudios.io.connection.ReusableConnectionBuilder;

import java.net.ServerSocket;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

/**
 * Used to build Server objects.
 *
 * @author Caleb Brinkman
 */
public class ServerBuilder
{
    private ServerSocket serverSocket;
    private ReusableConnectionBuilder connectionBuilder;

    /**
     * Build a Server using the properties supplied to this builder.
     *
     * @return The constructed Server
     *
     * @throws IllegalStateException If the ServerSocket or ReusableConnectionBuilder are not set.
     */
    public Server build() {
        if (serverSocket == null) {
            throw new IllegalStateException("ServerSocket must be set to build server");
        }
        if (connectionBuilder == null) {
            throw new IllegalStateException("ReusableConnectionBuilder must be set to build server");
        }
        return null;
    }

    /**
     * Build a Server using the given ServerSocket.`
     *
     * @param socket The ServerSocket.
     *
     * @return This ServerBuilder.
     */
    public ServerBuilder withServerSocket(ServerSocket socket) {
        this.serverSocket = socket;
        return this;
    }

    /**
     * Build a Server which will use the given ReusableConnectionBuilder to build new connections.
     *
     * @param builder The ReusableConnectionBuilder.
     *
     * @return This ServerBuilder.
     */
    public ServerBuilder withReusableConnectionBuilder(ReusableConnectionBuilder builder) {
        this.connectionBuilder = builder;
        return this;
    }

    /**
     * Build a Server which will execute the given tasks each time a Connection executes its contextual tasks.
     *
     * @param tasks The tasks to be executed with access to this server and an ExecutionContext
     *
     * @return This ServerBuilder.
     */
    @SafeVarargs
    public final ServerBuilder withContextualTasks(BiConsumer<Server, ExecutionContext>... tasks) {
        return this;
    }

    /**
     * Build a Server which will execute the given tasks each time a Connection executes its contextual tasks.
     *
     * @param tasks The tasks to be executed with access to this server and an ExecutionContext
     *
     * @return This ServerBuilder.
     */
    public ServerBuilder withContextualTasks(Iterable<BiConsumer<Server, ExecutionContext>> tasks) {
        return this;
    }

    /**
     * Build a Server which will execute the given callbacks when a Connection is added.
     *
     * @param callbacks The callbacks to execute.
     *
     * @return This ServerBuilder
     */
    public ServerBuilder withConnectionAddedCallbacks(Iterable<Consumer<Connection>> callbacks) {
        return this;
    }

    /**
     * Build a Server which will execute the given callbacks when a Connection is added.
     *
     * @param callbacks The callbacks to execute.
     *
     * @return This ServerBuilder
     */
    @SafeVarargs
    public final ServerBuilder withConnectionAddedCallbacks(Consumer<Connection>... callbacks) {
        return this;
    }

    /**
     * Build a Server which will execute the given callbacks when a Connection is removed.
     *
     * @param callbacks The callbacks to execute.
     *
     * @return This ServerBuilder
     */
    public ServerBuilder withConnectionRemovedCallbacks(Iterable<Consumer<Connection>> callbacks) {
        return this;
    }

    /**
     * Build a Server which will execute the given callbacks when a Connection is removed.
     *
     * @param callbacks The callbacks to execute.
     *
     * @return This ServerBuilder
     */
    @SafeVarargs
    public final ServerBuilder withConnectionRemovedCallbacks(Consumer<Connection>... callbacks) {
        return this;
    }

    /**
     * Build a Server which will execute the given callbacks after startup.
     *
     * @param callbacks The callbacks to execute.
     *
     * @return This ServerBuilder
     */
    public ServerBuilder withStartupCallbacks(Iterable<Consumer<Connection>> callbacks) {
        return this;
    }

    /**
     * Build a Server which will execute the given callbacks after startup.
     *
     * @param callbacks The callbacks to execute.
     *
     * @return This ServerBuilder
     */
    @SafeVarargs
    public final ServerBuilder withStartupCallbacks(Consumer<Connection>... callbacks) {
        return this;
    }

    /**
     * Build a Server which will execute the given callbacks after shutdown.
     *
     * @param callbacks The callbacks to execute.
     *
     * @return This ServerBuilder
     */
    public ServerBuilder withShutdownCallbacks(Iterable<Consumer<Connection>> callbacks) {
        return this;
    }

    /**
     * Build a Server which will execute the given callbacks after shutdown.
     *
     * @param callbacks The callbacks to execute.
     *
     * @return This ServerBuilder
     */
    @SafeVarargs
    public final ServerBuilder withShutdownCallbacks(Consumer<Connection>... callbacks) {
        return this;
    }
}

@@ -225,16 +225,45 @@
 Socket;%0A
+import java.util.LinkedList;%0A
 import j
@@ -292,16 +292,16 @@
 nsumer;%0A
-
 import j
@@ -428,16 +428,462 @@
 ilder%0A%7B%0A
+    private final Iterable%3CBiConsumer%3CServer, ExecutionContext%3E%3E contextualTasks = new LinkedList%3C%3E();%0A    private final Iterable%3CConsumer%3CConnection%3E%3E addedCallbacks = new LinkedList%3C%3E();%0A    private final Iterable%3CConsumer%3CConnection%3E%3E removedCallbacks = new LinkedList%3C%3E();%0A    private final Iterable%3CConsumer%3CServer%3E%3E startupCallbacks = new LinkedList%3C%3E();%0A    private final Iterable%3CConsumer%3CServer%3E%3E shutdownCallbacks = new LinkedList%3C%3E();%0A
     priv
@@ -1515,32 +1515,33 @@
 er%22);%0A        %7D%0A
+%0A
         return n
@@ -1540,19 +1540,254 @@
 return n
-ull
+ew Server(%0A              serverSocket,%0A              connectionBuilder,%0A              contextualTasks,%0A              addedCallbacks,%0A              removedCallbacks,%0A              startupCallbacks,%0A              shutdownCallbacks%0A        )
 ;%0A    %7D%0A

Add fields, construct Server with them