/*
 * Copyright 2016-present Open Networking Laboratory
 *
 * 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.google.common.io.ByteStreams;
import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
import org.onosproject.checkstyle.CheckstyleRunner;

import java.io.IOException;
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.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static java.nio.file.StandardOpenOption.*;

/**
 * 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) {
                        System.err.println("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) {
            System.out.println("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();
                System.err.println("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()));

        // 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 {
                BuckTaskContext context = new BuckTaskContext(socket.getInputStream());
                String taskName = context.taskName();
                if (!taskName.isEmpty()) {
                    BuckTask task = tasks.get(taskName);
                    if (task != null) {
                        System.out.println(String.format("Executing task '%s'", taskName));
                        task.execute(context);
                        for (String line : context.output()) {
                            output(socket, line);
                        }
                    } else {
                        String message = String.format("No task named '%s'", taskName);
                        System.out.print(message);
                        output(socket, message);
                    }
                }
                socket.getOutputStream().flush();
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

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