/*
 * Copyright 2016-present Open Networking Foundation
 *
 * 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 org.onosproject.buckdaemon;

import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
import org.onosproject.checkstyle.CheckstyleRunner;

import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static java.nio.file.StandardOpenOption.CREATE;
import static java.nio.file.StandardOpenOption.WRITE;

/**
 * Buck daemon process.
 */
public final class BuckDaemon {

    private static long POLLING_INTERVAL = 1000; //ms

    private final Map<String, BuckTask> tasks = new HashMap<>();
    private final String portLock;
    private final String buckPid;

    // Public construction forbidden
    private BuckDaemon(String[] args) {
        portLock = args[0];
        buckPid = args[1];
    }

    /**
     * Main entry point for the daemon.
     *
     * @param args command-line arguments
     */
    public static void main(String[] args)
            throws CheckstyleException, IOException {
        BuckDaemon daemon = new BuckDaemon(args);
        daemon.registerTasks();
        daemon.startServer();
    }

    /**
     * Registers re-entrant tasks by their task name.
     */
    private void registerTasks() {
        tasks.put("checkstyle", new CheckstyleRunner(System.getProperty("checkstyle.config"),
                                                     System.getProperty("checkstyle.suppressions")));
        // tasks.put("swagger", new SwaggerGenerator());
    }

    /**
     * Monitors another PID and exit when that process exits.
     */
    private void watchProcess(String pid) {
        if (pid == null || pid.equals("0")) {
            return;
        }
        Timer timer = new Timer(true); // start as a daemon, so we don't hang shutdown
        timer.scheduleAtFixedRate(new TimerTask() {
            private String cmd = "kill -s 0 " + pid;

            @Override
            public void run() {
                try {
                    Process p = Runtime.getRuntime().exec(cmd);
                    p.waitFor();
                    if (p.exitValue() != 0) {
                        debug("shutting down...");
                        System.exit(0);
                    }
                } catch (IOException | InterruptedException e) {
                    //no-op
                    e.printStackTrace();
                }
            }
        }, POLLING_INTERVAL, POLLING_INTERVAL);
    }

    /**
     * Initiates a server.
     */
    private void startServer() throws IOException, CheckstyleException {
        // Use a file lock to ensure only one copy of the daemon runs
        Path portLockPath = Paths.get(portLock);
        FileChannel channel = FileChannel.open(portLockPath, WRITE, CREATE);
        FileLock lock = channel.tryLock();
        if (lock == null) {
            debug("Server is already running");
            System.exit(1);
        } //else, hold the lock until the JVM exits

        // Start the server and bind it to a random port
        ServerSocket server = new ServerSocket(0);

        // Monitor the parent buck process
        watchProcess(buckPid);

        // Set up hook to clean up after ourselves
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            try {
                channel.truncate(0);
                channel.close();
                debug("tear down...");
                Files.delete(portLockPath);
            } catch (IOException e) {
                //no-op: shutting down
                e.printStackTrace();
            }
        }));

        // Write the bound port to the port file
        int port = server.getLocalPort();
        channel.truncate(0);
        channel.write(ByteBuffer.wrap(Integer.toString(port).getBytes()));
        channel.force(false); // flush the port number to disk

        // Instantiate a Checkstyle runner and executor; serve until exit...
        ExecutorService executor = Executors.newCachedThreadPool();
        while (true) {
            try {
                executor.submit(new BuckTaskRunner(server.accept()));
            } catch (Exception e) {
                e.printStackTrace();
                //no-op
            }
        }
    }

    /**
     * Runnable capable of invoking the appropriate Buck task with input
     * consumed form the specified socket and output produced back to that
     * socket.
     */
    private class BuckTaskRunner implements Runnable {

        private final Socket socket;

        public BuckTaskRunner(Socket socket) {
            this.socket = socket;
        }

        @Override
        public void run() {
            try {
                try {
                    socket.setSoTimeout(1_000); //reads should time out after 1 second
                    BuckTaskContext context = new BuckTaskContext(socket.getInputStream());

                    String taskName = context.taskName();
                    BuckTask task = tasks.get(taskName);
                    if (task != null) {
                        debug(String.format("Executing task '%s'", taskName));
                        try {
                            task.execute(context);
                            for (String line : context.output()) {
                                send(socket, line);
                            }
                            // TODO should we catch Exception, RuntimeException, or something specific?
                        } catch (Throwable e) {
                            e.printStackTrace(new PrintStream(socket.getOutputStream()));
                        }
                    } else {
                        String message = String.format("No task named '%s'", taskName);
                        debug(message);
                        send(socket, message);
                    }
                } catch (Throwable e) {
                    StringWriter writer = new StringWriter();
                    e.printStackTrace(new PrintWriter(writer));
                    String stacktrace = writer.toString();
                    debug(stacktrace);
                    send(socket, stacktrace);
                }
                socket.getOutputStream().flush();
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    private static void send(Socket socket, String line) throws IOException {
        socket.getOutputStream().write((line + "\n").getBytes());
    }

    private static void debug(String message) {
        // no-op; print to System.out if needed
    }
}
