package net.zephyrizing.http_server_test.integration;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import net.zephyrizing.http_server.HttpServer;

import org.junit.Ignore;
import org.junit.Test;

import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;

public class SmokeTest {
    public class ServerThread extends Thread {
        Integer port;
        String directory;

        public ServerThread() { this(null, null); }
        public ServerThread(Integer port) { this(port, null); }
        public ServerThread(String directory) { this(null, directory); }
        public ServerThread(Integer port, String directory) {
            this.port = port;
            this.directory = directory;
        }

        @Override
        public void run() {
            PrintStream oldErr = System.err;
            PrintStream newErr = new PrintStream(new ByteArrayOutputStream());
            System.setErr(newErr);
            try {
                HttpServer.main(buildOptions());
            } catch (InterruptedException e) {
            } finally {
                System.setErr(oldErr);
            }
        }

        public String[] buildOptions() {
            List<String> opts = new ArrayList<String>();
            int i = 0;
            if (port != null) {
                opts.add("-p");
                opts.add(port.toString());
            }
            if (directory != null) {
                opts.add("-d");
                opts.add(directory);
            }
            return opts.toArray(new String[0]);
        }
    }

    public void pingServer(int port) throws IOException {
        try (Socket s = new Socket(InetAddress.getLocalHost(), port);
             PrintWriter out = new PrintWriter(s.getOutputStream())) {
            out.append("\r\n").append("\r\n").append("\r\n");
        }
    }

    @Test
    public void runDefaultServer() throws Exception {
        ServerThread server = new ServerThread();
        assertThat(Arrays.asList(server.buildOptions()), everyItem(notNullValue(String.class)));

        server.start();
        Thread.sleep(100);

        assertTrue(server.isAlive());

        server.interrupt();
        pingServer(5000);
    }

    @Test
    public void runServerWithPortArgument() throws Exception {
        int port = 10000;
        ServerThread server = new ServerThread(port);
        assertThat(Arrays.asList(server.buildOptions()), everyItem(notNullValue(String.class)));

        server.start();
        Thread.sleep(100);

        assertTrue(server.isAlive());

        server.interrupt();
        pingServer(port);
    }

    @Test
    public void runServerWithDirectoryArgument() throws Exception {
        int port = 12000;
        ServerThread server = new ServerThread(port, "public");
        assertThat(Arrays.asList(server.buildOptions()), everyItem(notNullValue(String.class)));

        server.start();
        Thread.sleep(100);

        assertTrue(server.isAlive());

        server.interrupt();
        pingServer(port);
    }

    @Test
    public void runServerAndGetResponse() throws Exception {
        int port = 12000;
        ServerThread server = new ServerThread(port, "public");
        assertThat(Arrays.asList(server.buildOptions()), everyItem(notNullValue(String.class)));

        server.start();
        Thread.sleep(100);

        try (Socket socket = new Socket("localhost", port);
             PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
             BufferedReader in = new BufferedReader(
                 new InputStreamReader(socket.getInputStream()));) {
            out.print("GET /.gitkeep HTTP/1.1\r\n");
            out.print("Host: localhost\r\n");
            out.print("\r\n");
            out.flush();

            String line = in.readLine();
            assertThat(line, equalTo("HTTP/1.1 200 OK"));

            line = in.readLine();
            assertThat(line, equalTo(""));

            line = in.readLine();
            assertThat(line, equalTo(null));
        }
        server.interrupt();
        pingServer(port);
    }
}

@@ -1824,25 +1824,24 @@
   %7D%0A
+%0A
     
-%7D%0A%0A
     p
-ublic
+rivate
  voi
@@ -1876,32 +1876,36 @@
 s IOException %7B%0A
+    
         try (Soc
@@ -1963,32 +1963,36 @@
 );%0A             
+ 
+   
 PrintWriter out 
@@ -2041,24 +2041,28 @@
             
+  
+  
 out.append(%22
@@ -2091,32 +2091,360 @@
 append(%22%5Cr%5Cn%22);%0A
+            %7D%0A        %7D%0A%0A        public void shutdownServer() %7B%0A            this.interrupt();%0A            try %7B%0A                int port = 5000;%0A                if (this.port != null) %7B%0A                    port = this.port;%0A                %7D%0A                pingServer(port);%0A            %7D catch (IOException e) %7B%0A            %7D%0A
         %7D%0A    %7D%0A
@@ -2766,44 +2766,23 @@
 ver.
-interrupt();%0A        ping
+shutdown
 Server(
-5000
 );%0A 
@@ -3148,44 +3148,23 @@
 ver.
-interrupt();%0A        ping
+shutdown
 Server(
-port
 );%0A 
@@ -3259,33 +3259,33 @@
     int port = 1
-2
+0
 000;%0A        Ser
@@ -3545,44 +3545,23 @@
 ver.
-interrupt();%0A        ping
+shutdown
 Server(
-port
 );%0A 
@@ -3657,17 +3657,17 @@
 port = 1
-2
+0
 000;%0A   
@@ -4581,44 +4581,23 @@
 ver.
-interrupt();%0A        ping
+shutdown
 Server(
-port
 );%0A 

Move server shutdown code into the thread class