/*
 * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package javacserver.client;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Reader;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javacserver.server.Server;
import javacserver.shared.PortFileInaccessibleException;
import javacserver.shared.Protocol;
import javacserver.shared.Result;
import javacserver.util.AutoFlushWriter;
import javacserver.util.Log;

/**
 * The javacserver client. This is called from the makefiles, and is responsible for passing the command
 * line on to a server instance running javac, starting a new server if needed.
 */
public class Client {
    private static final Log.Level LOG_LEVEL = Log.Level.INFO;

    // Wait 4 seconds for response, before giving up on javac server.
    private static final int CONNECTION_TIMEOUT = 4000;
    private static final int MAX_CONNECT_ATTEMPTS = 10;
    private static final int WAIT_BETWEEN_CONNECT_ATTEMPTS = 2000;

    private final ClientConfiguration conf;

    public Client(ClientConfiguration conf) {
        this.conf = conf;
    }

    public static void main(String... args) {
        Log.setLogForCurrentThread(new Log(
                new AutoFlushWriter(new OutputStreamWriter(System.out)),
                new AutoFlushWriter(new OutputStreamWriter(System.err))));
        Log.setLogLevel(LOG_LEVEL);

        ClientConfiguration conf = ClientConfiguration.fromCommandLineArguments(args);
        if (conf == null) {
            System.exit(Result.CMDERR.exitCode);
        }

        Client client = new Client(conf);
        int exitCode = client.dispatchToServer();

        System.exit(exitCode);
    }

    private int dispatchToServer() {
        try {
            // Check if server seems to be already running
            if (!conf.portFile().hasValidValues()) {
                // Fork a new server and wait for it to start
                startNewServer();
            }

            try (Socket socket = tryConnect()) {
                BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                PrintWriter out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));

                Protocol.sendCommand(out, conf.javacArgs());
                int exitCode = Protocol.readResponse(in);

                return exitCode;
            }
        } catch (PortFileInaccessibleException e) {
            Log.error("Port file inaccessible.");
            return Result.ERROR.exitCode;
        } catch (IOException ioe) {
            Log.error("IOException caught during compilation: " + ioe.getMessage());
            Log.debug(ioe);
            return Result.ERROR.exitCode;
        } catch (InterruptedException ie) {
            Thread.currentThread().interrupt(); // Restore interrupt
            Log.error("Compilation interrupted.");
            Log.debug(ie);
            return Result.ERROR.exitCode;
        }
    }

    /*
     * Makes MAX_CONNECT_ATTEMPTS attempts to connect to server.
     */
    private Socket tryConnect() throws IOException, InterruptedException {
        int attempt = 0;

        while (true) {
            Log.debug("Trying to connect. Attempt " + (++attempt) + " of " + MAX_CONNECT_ATTEMPTS);
            try {
                Socket socket = new Socket();
                InetAddress localhost = InetAddress.getByName(null);
                InetSocketAddress address = new InetSocketAddress(localhost, conf.portFile().getPort());
                socket.connect(address, CONNECTION_TIMEOUT);
                Log.debug("Connected");
                return socket;
            } catch (IOException ex) {
                Log.error("Connection attempt failed: " + ex.getMessage());
                if (attempt >= MAX_CONNECT_ATTEMPTS) {
                    Log.error("Giving up");
                    throw new IOException("Could not connect to server after " + MAX_CONNECT_ATTEMPTS + " attempts with timeout " + CONNECTION_TIMEOUT, ex);
                }
            }
            Thread.sleep(WAIT_BETWEEN_CONNECT_ATTEMPTS);
        }
    }

    /*
     * Fork a server process and wait for server to come around
     */
    private void startNewServer() throws IOException, InterruptedException {
        List<String> cmd = new ArrayList<>();
        // conf.javaCommand() is how to start java in the way we want to run
        // the server
        cmd.addAll(Arrays.asList(conf.javaCommand().split(" ")));
        // javacserver.server.Server is the server main class
        cmd.add(Server.class.getName());
        // and it expects a port file path
        cmd.add(conf.portFile().getFilename());

        Process serverProcess;
        Log.debug("Starting server. Command: " + String.join(" ", cmd));
        try {
            // If the cmd for some reason can't be executed (file is not found,
            // or is not executable for instance) this will throw an
            // IOException
            serverProcess = new ProcessBuilder(cmd).redirectErrorStream(true).start();
        } catch (IOException ex) {
            // Message is typically something like:
            // Cannot run program "xyz": error=2, No such file or directory
            Log.error("Failed to create server process: " + ex.getMessage());
            Log.debug(ex);
            throw new IOException(ex);
        }

        // serverProcess != null at this point.
        try {
            // Throws an IOException if no valid values materialize
            conf.portFile().waitForValidValues();
        } catch (IOException ex) {
            // Process was started, but server failed to initialize. This could
            // for instance be due to the JVM not finding the server class,
            // or the server running in to some exception early on.
            Log.error("javacserver server process failed to initialize: " + ex.getMessage());
            Log.error("Process output:");
            Reader serverStdoutStderr = new InputStreamReader(serverProcess.getInputStream());
            try (BufferedReader br = new BufferedReader(serverStdoutStderr)) {
                br.lines().forEach(Log::error);
            }
            Log.error("<End of process output>");
            try {
                Log.error("Process exit code: " + serverProcess.exitValue());
            } catch (IllegalThreadStateException e) {
                // Server is presumably still running.
            }
            throw new IOException("Server failed to initialize: " + ex.getMessage(), ex);
        }
    }
}
