package WebSide;

import GRPCConnection.AddressProxy;
import GRPCConnection.GRPCClient.GRPCClient;
import com.google.gson.Gson;
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpContext;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpServer;
import org.apache.zookeeper.KeeperException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.awt.*;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Executors;

public class WebServer
{
    private final String Search_EndPoint = "/search";
    private GRPCClient grpcClient;
    private AddressProxy addressProxy;
    private static final Logger logger = LoggerFactory.getLogger(WebServer.class);
    private final int port;
    private HttpServer server;

    public WebServer(int port) throws IOException, InterruptedException
    {
        this.port = port;
        grpcClient = new GRPCClient();
        addressProxy = AddressProxy.start();
    }
    public static void main(String[] args) throws IOException, InterruptedException {
        int serverPort = 5566;
        if (args.length == 1) {
            serverPort = Integer.parseInt(args[0]);
        }

        WebServer webServer = new WebServer(serverPort);
        webServer.startServer();

        System.out.println("Server is listening on port " + serverPort);
        logger.info("Server is listening on port " + serverPort);
    }
    public void startServer() {
        try
        {
            this.server = HttpServer.create(new InetSocketAddress(port), 0);
            logger.info("Server Started at : " + System.nanoTime());
            System.out.println("Server Started");
        }
        catch (IOException e) {
            logger.error("Server failed to Start at : " + System.nanoTime());
            System.out.println("Server failed");
            throw new RuntimeException(e);
        }

        HttpContext searchContext = server.createContext(Search_EndPoint);

        searchContext.setHandler(this::handleSearchRequest);

        server.setExecutor(Executors.newFixedThreadPool(8));
        server.start();

    }

    private void handleSearchRequest(HttpExchange exchange) throws IOException {
        logger.info("Search Request at " + System.nanoTime());
        if (!exchange.getRequestMethod().equalsIgnoreCase("post")) {
            exchange.close();
            return;
        }

        byte[] requestBytes = exchange.getRequestBody().readAllBytes();

        String query = new String(requestBytes);
        List<String> files = new ArrayList<>();
        try
        {
            String o = addressProxy.getAddress();
            files = grpcClient.search(query , o);
        }
        catch (InterruptedException | KeeperException e)
        {
            files.add("Some Thing Went Wrong !!");
        }

        sendResponse(files, exchange);

    }

    private void sendResponse(List<String> files, HttpExchange exchange) throws IOException {
        String s ="";
        for(String file : files)
        {
            s += file;
            s+="\n";
        }
        exchange.sendResponseHeaders(200, s.getBytes().length);
        OutputStream outputStream = exchange.getResponseBody();
        outputStream.write(s.getBytes());
        outputStream.flush();
        outputStream.close();
        exchange.close();
    }

    private void sendResponseJson(List<String> responseList, HttpExchange exchange) throws IOException
    {
        Gson gson = new Gson();

        String jsonResponse = gson.toJson(responseList);

        exchange.getResponseHeaders().set("Content-Type", "application/json");

        exchange.sendResponseHeaders(200, jsonResponse.getBytes().length);

        OutputStream outputStream = exchange.getResponseBody();

        outputStream.write(jsonResponse.getBytes());
        outputStream.flush();
        outputStream.close();
        exchange.close();
    }
}
