/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.build.gradle.external.cmake.server;

import com.android.annotations.NonNull;
import com.android.annotations.VisibleForTesting;
import com.android.build.gradle.external.cmake.server.receiver.InteractiveMessage;
import com.android.build.gradle.external.cmake.server.receiver.InteractiveProgress;
import com.android.build.gradle.external.cmake.server.receiver.ServerReceiver;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Implementation of version 1 of Cmake server for Cmake versions 3.7.1. Cmake server or a long
 * running mode which allows a client to configure and request buildsystem information generated by
 * Cmake. More info: https://cmake.org/cmake/help/v3.7/manual/cmake-server.7.html
 */
public class ServerProtocolV1 implements Server {
    // Messages sent to and from the Cmake server are wrapped in the header and footer strings.
    public static final String CMAKE_SERVER_HEADER_MSG = "[== \"CMake Server\" ==[";
    public static final String CMAKE_SERVER_FOOTER_MSG = "]== \"CMake Server\" ==]";

    // When configuring a given project, Cmake server reports progress and these could contain
    // compiler information. The compiler info is contained within these prefix/suffix messages.
    // Note: These progress messages will be used as a fallback to determine the compiler info only
    // when compile_commands.json file is not present.
    public static final String CMAKE_SERVER_C_COMPILER_PREFIX = "Check for working C compiler: ";
    public static final String CMAKE_SERVER_CXX_COMPILER_PREFIX =
            "Check for working CXX compiler: ";
    public static final String CMAKE_SERVER_C_COMPILER_SUFFIX = " -- works";

    // Reader and writers to communicate with Cmake server.
    private BufferedReader input;
    private BufferedWriter output;
    // Cmake's install path.
    private final File cmakeInstallPath;
    // Messages, signals etc received from Cmake server.
    private final ServerReceiver serverReceiver;
    // Cached hello result, used to get Cmake server versions.
    private HelloResult helloResult = null;
    // Indicates if we are connected to the Cmake server.
    private boolean connected = false;
    // Indicates if we have configured the given project.
    private boolean configured = false;
    // Indicates if we have computed the given project.
    private boolean computed = false;

    // Interactive messages received when configuring the project.
    private List<InteractiveMessage> configureMessages;
    // Process builder used primarily for testing.
    Process process = null;

    ServerProtocolV1(@NonNull File cmakeInstallPath, @NonNull ServerReceiver serverReceiver) {
        this.cmakeInstallPath = cmakeInstallPath;
        this.serverReceiver = serverReceiver;
    }

    /**
     * This constructor is used only for testing purpose, to pass mock process, buffered
     * input/output etc.
     */
    @VisibleForTesting
    ServerProtocolV1(
            @NonNull File cmakeInstallPath,
            @NonNull ServerReceiver serverReceiver,
            Process process,
            BufferedReader input,
            BufferedWriter output) {
        this.cmakeInstallPath = cmakeInstallPath;
        this.serverReceiver = serverReceiver;
        this.process = process;
        this.input = input;
        this.output = output;
    }

    @Override
    public void finalize() {
        try {
            disconnect();
        } catch (IOException e) {
            diagnostic("Error when disconnecting from Cmake server: %s", e.toString());
        }
    }

    @Override
    public boolean connect() throws IOException {
        init();
        helloResult = decodeResponse(HelloResult.class);
        connected = ServerUtils.isHelloResultValid(helloResult);
        return connected;
    }

    @Override
    public void disconnect() throws IOException {
        if (input != null) {
            input.close();
            input = null;
        }
        if (output != null) {
            output.close();
            output = null;
        }

        if (process != null) {
            process.destroy();
            process = null;
        }

        connected = false;
        configured = false;
        computed = false;
        configureMessages = null;
        helloResult = null;
    }

    @Override
    public boolean isConnected() {
        return connected;
    }

    @NonNull
    @Override
    public List<ProtocolVersion> getSupportedVersion() {
        if (helloResult == null || helloResult.supportedProtocolVersions == null) {
            return null;
        }
        List<ProtocolVersion> result = new ArrayList<>();
        for (ProtocolVersion protocolVersion : helloResult.supportedProtocolVersions) {
            if (protocolVersion.major == 1 && protocolVersion.minor == 0) {
                result.add(protocolVersion);
                break;
            }
        }
        return result;
    }

    @NonNull
    @Override
    public HandshakeResult handshake(@NonNull HandshakeRequest handshakeRequest)
            throws IOException {
        if (!connected) {
            throw new RuntimeException("Not connected to Cmake server.");
        }
        writeMessage(new GsonBuilder().setPrettyPrinting().create().toJson(handshakeRequest));
        return decodeResponse(HandshakeResult.class);
    }

    @NonNull
    @Override
    public ConfigureCommandResult configure(@NonNull String... cacheArguments) throws IOException {
        if (!connected) {
            throw new RuntimeException("Not connected to Cmake server.");
        }

        ConfigureRequest configureRequest = new ConfigureRequest();

        // Insert a blank element to work around a bug in Cmake 3.7.1 where the first element is
        // ignored.
        configureRequest.cacheArguments = new String[cacheArguments.length + 1];
        configureRequest.cacheArguments[0] = "";
        System.arraycopy(
                cacheArguments, 0, configureRequest.cacheArguments, 1, cacheArguments.length);

        writeMessage(new GsonBuilder().setPrettyPrinting().create().toJson(configureRequest));
        configureMessages = new ArrayList<>();
        ConfigureResult configureResult = decodeResponse(ConfigureResult.class, configureMessages);
        configured = ServerUtils.isConfigureResultValid(configureResult);

        return new ConfigureCommandResult(
                configureResult,
                !configureMessages.isEmpty()
                        ? getInteractiveMessagesAsString(configureMessages)
                        : "");
    }

    @NonNull
    @Override
    public ComputeResult compute() throws IOException {
        if (!connected) {
            throw new RuntimeException("Not connected to Cmake server.");
        }

        if (!configured) {
            throw new RuntimeException(
                    "Cmake server has not been configured successfully, unable to compute.");
        }

        writeMessage("{\"type\":\"compute\"}");
        ComputeResult computeResult = decodeResponse(ComputeResult.class);
        computed = ServerUtils.isComputedResultValid(computeResult);
        return computeResult;
    }

    @NonNull
    @Override
    public CodeModel codemodel() throws IOException {
        if (!connected) {
            throw new RuntimeException("Not connected to Cmake server.");
        }

        if (!computed) {
            throw new RuntimeException("Need to compute before requesting for codemodel.");
        }

        writeMessage("{\"type\":\"codemodel\"}");
        return decodeResponse(CodeModel.class);
    }

    @NonNull
    @Override
    public CacheResult cache() throws IOException {
        if (!connected) {
            throw new RuntimeException("Not connected to Cmake server.");
        }

        CacheRequest request = new CacheRequest();
        writeMessage(new GsonBuilder().setPrettyPrinting().create().toJson(request));
        return decodeResponse(CacheResult.class);
    }

    @NonNull
    @Override
    public GlobalSettings globalSettings() throws IOException {
        if (!connected) {
            throw new RuntimeException("Not connected to Cmake server.");
        }

        writeMessage("{\"type\":\"globalSettings\"}");
        return decodeResponse(GlobalSettings.class);
    }

    @NonNull
    @Override
    public String getCCompilerExecutable() {
        final String prefixMessage = "Check for working C compiler: ";
        final String suffixMessage = " -- works";

        return hackyGetLangExecutable(prefixMessage, suffixMessage);
    }

    @NonNull
    @Override
    public String getCppCompilerExecutable() {
        final String prefixMessage = "Check for working CXX compiler: ";
        final String suffixMessage = " -- works";

        return hackyGetLangExecutable(prefixMessage, suffixMessage);
    }

    @NonNull
    @Override
    public String getCmakePath() {
        return cmakeInstallPath.getAbsolutePath();
    }

    @NonNull
    public HelloResult getHelloResult() {
        return helloResult;
    }

    // Helper functions

    /**
     * Ideally, we should use compile_commands.json generated by Cmake to get C and Cxx compiler
     * information. If for whatever reason the file is not present (or not generated), we fall back
     * to check the progress messages generated Cmake server when configuring, to get the desired
     * information.
     *
     * @param prefixMessage - prefix string to search
     * @param suffixMessage - suffix string to search
     * @return C/CXX compiler
     */
    private String hackyGetLangExecutable(
            @NonNull String prefixMessage, @NonNull String suffixMessage) {
        if (configureMessages == null || configureMessages.isEmpty()) {
            return null;
        }

        for (InteractiveMessage message : configureMessages) {
            if (message.message == null
                    || !message.message.startsWith(prefixMessage)
                    || !message.message.endsWith(suffixMessage)) {
                continue;
            }
            return message.message.substring(
                    prefixMessage.length(), message.message.length() - suffixMessage.length());
        }

        return null;
    }

    /**
     * Initializes the server.
     *
     * @throws IOException I/O failure
     */
    private void init() throws IOException {
        if (process == null) {
            ProcessBuilder processBuilder = getCmakeServerProcessBuilder();
            processBuilder.environment().putAll(new ProcessBuilder().environment());
            process = processBuilder.start();
        }

        if (input == null) {
            input = new BufferedReader(new InputStreamReader(process.getInputStream()));
        }
        if (output == null) {
            output = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
        }
    }

    /**
     * Prints diagnostic messages.
     *
     * @param format - diagnostic message format
     * @param args - diagnostic message arguments
     */
    private void diagnostic(String format, Object... args) {
        if (serverReceiver.getDiagnosticReceiver() != null) {
            serverReceiver.getDiagnosticReceiver().receive(String.format(format, args));
        }
    }

    /**
     * Constructs a Cmake server process builder.
     *
     * @return process builder
     */
    private ProcessBuilder getCmakeServerProcessBuilder() {
        final String cmakeBinPath = new File(this.cmakeInstallPath, "cmake").getPath();
        return new ProcessBuilder(cmakeBinPath, "-E", "server", "--experimental", "--debug");
    }

    /**
     * Decodes the responses received during Cmake server interactions for a given request.
     *
     * @param clazz Class object that represents the response class
     * @return decoded response
     * @throws IOException I/O failure
     */
    private <T> T decodeResponse(Class<T> clazz) throws IOException {
        return decodeResponse(clazz, null);
    }

    private <T> T decodeResponse(Class<T> clazz, List<InteractiveMessage> interactiveMessages)
            throws IOException {
        Gson gson = new GsonBuilder().create();
        String message = readMessage();
        String messageType = gson.fromJson(message, TypeOfMessage.class).type;

        final List supportedTypes = Arrays.asList("message", "progress", "signal");
        // Process supported interactive messages.
        // For a given command, the CMake server would respond with message types
        // 0 or more of (message | progress | signal)
        // and finally terminates with a message with message types
        // (hello | reply | error)
        // More info:
        // https://cmake.org/cmake/help/v3.7/manual/cmake-server.7.html#general-message-layout
        while (supportedTypes.contains(messageType)) {
            switch (messageType) {
                case "message":
                    if (serverReceiver.getMessageReceiver() != null) {
                        InteractiveMessage interactiveMessage =
                                gson.fromJson(message, InteractiveMessage.class);
                        serverReceiver.getMessageReceiver().receive(interactiveMessage);
                        // Record the interactive messages only if need be.
                        if (interactiveMessages != null) {
                            serverReceiver.getMessageReceiver().receive(interactiveMessage);
                            interactiveMessages.add(interactiveMessage);
                        }
                    }
                    break;
                case "progress":
                    if (serverReceiver.getProgressReceiver() != null) {
                        serverReceiver
                                .getProgressReceiver()
                                .receive(gson.fromJson(message, InteractiveProgress.class));
                        break;
                    }
                    break;
                case "signal":
                    if (serverReceiver.getProgressReceiver() != null) {
                        serverReceiver
                                .getProgressReceiver()
                                .receive(gson.fromJson(message, InteractiveProgress.class));
                        break;
                    }
            }
            message = readMessage();
            messageType = gson.fromJson(message, TypeOfMessage.class).type;
        }

        // Process the final message.
        switch (messageType) {
            case "hello":
            case "reply":
                if (serverReceiver.getDeserializationMonitor() != null) {
                    serverReceiver.getDeserializationMonitor().receive(message, clazz);
                }
                return gson.fromJson(message, clazz);
            case "error":
                if (serverReceiver.getMessageReceiver() != null) {
                    InteractiveMessage interactiveMessage =
                            gson.fromJson(message, InteractiveMessage.class);
                    serverReceiver.getMessageReceiver().receive(interactiveMessage);
                }
                return null;
            default:
                throw new RuntimeException(
                        "Unsupported message type " + messageType + " received from CMake server.");
        }
    }

    /**
     * Appends the messages from the given list of InteractiveMessage to return it as a single
     * string.
     *
     * @param interactiveMessages - list of interactive messages received from Cmake server
     * @return A single string with all the messages from interactive messages.
     */
    private static String getInteractiveMessagesAsString(
            List<InteractiveMessage> interactiveMessages) {
        StringBuilder result = new StringBuilder();
        for (InteractiveMessage interactiveMessage : interactiveMessages) {
            result.append(interactiveMessage.message).append("\n");
        }

        return result.toString();
    }

    /**
     * Reads a line from Cmake server
     *
     * @return a line read from Cmake servers response
     * @throws IOException I/O failure
     */
    private String readLine() throws IOException {
        final String line = input.readLine();
        diagnostic(line + "\n");
        return line;
    }

    /**
     * Writes a string to Cmake server
     *
     * @throws IOException I/O failure
     */
    private void writeLine(String message) throws IOException {
        diagnostic("%s\n", message);
        output.write(message);
        output.newLine();
    }

    /**
     * Reads until the expected string is found. Skip unexpected (or non-conforming) messages if
     * need be until the expected string is found. Note: The CMake server sometimes writes
     * non-conforming messages (by deviating from the general message layout: https://goo.gl/d4XMmB)
     * to stdout, these are harmless (i.e., they don't break the build) and hence need to be
     * ignored.
     */
    private void readExpected(@NonNull String expectedString) throws IOException {
        String line = readLine();
        while (!line.equals(expectedString)) {
            // Skip a blank line if there is one.
            if (!line.isEmpty() && serverReceiver.getDiagnosticReceiver() != null) {
                serverReceiver.getDiagnosticReceiver().receive(line);
            }
            line = readLine();
        }
    }

    /**
     * Reads a message send by CMake server. CMake Server sends the messages wrapped within a
     * defined header and footer string, this function reads everything inbetween the header and
     * footer and returns it. General message layout we expect from CMake Server:
     *
     * <p>[non-conforming messages from CMake Server]
     *
     * <p>[== "CMake Server" ==[
     *
     * <p>InteractiveMessage
     *
     * <p>[non-conforming messages from CMake Server]
     *
     * <p>]== "CMake Server" ==]
     *
     * @return The string contained within the header and footer
     * @throws IOException I/O failure
     */
    private String readMessage() throws IOException {
        readExpected(CMAKE_SERVER_HEADER_MSG);
        final String line = readLine();
        readExpected(CMAKE_SERVER_FOOTER_MSG);
        return line;
    }

    /**
     * Writes a message wrapped within the header and footer.
     *
     * @param message string to be sent to Cmake server
     * @throws IOException I/O failure
     */
    private void writeMessage(String message) throws IOException {
        writeLine(CMAKE_SERVER_HEADER_MSG);
        writeLine(message);
        writeLine(CMAKE_SERVER_FOOTER_MSG);
        output.flush();
    }
}
