/*
 * Copyright (c) 2015, 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.
 *
 * 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.
 */
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * This is a framework to launch an app that could be synchronized with caller
 * to make further attach actions reliable across supported platforms

 * Caller example:
 *   SmartTestApp a = SmartTestApp.startApp(cmd);
 *     // do something
 *   a.stopApp();
 *
 *   or fine grained control
 *
 *   a = new SmartTestApp("MyLock.lck");
 *   a.createLock();
 *   a.runApp();
 *   a.waitAppReady();
 *     // do something
 *   a.deleteLock();
 *   a.waitAppTerminate();
 *
 *  Then you can work with app output and process object
 *
 *   output = a.getAppOutput();
 *   process = a.getProcess();
 *
 */
public class LingeredApp {

    private static final long spinDelay = 1000;

    private final String lockFileName;
    private long lockCreationTime;
    private Process appProcess;
    private final ArrayList<String> storedAppOutput;

    /*
     * Drain child process output, store it into string array
     */
    class InputGobbler extends Thread {

        InputStream is;
        List<String> astr;

        InputGobbler(InputStream is, List<String> astr) {
            this.is = is;
            this.astr = astr;
        }

        public void run() {
            try {
                InputStreamReader isr = new InputStreamReader(is);
                BufferedReader br = new BufferedReader(isr);
                String line = null;
                while ((line = br.readLine()) != null) {
                    astr.add(line);
                }
            } catch (IOException ex) {
                // pass
            }
        }
    }

    /**
     * Create LingeredApp object on caller side. Lock file have be a valid filename
     * at writable location
     *
     * @param lockFileName - the name of lock file
     */
    public LingeredApp(String lockFileName) {
        this.lockFileName = lockFileName;
        this.storedAppOutput = new ArrayList();
    }

    /**
     *
     * @return name of lock file
     */
    public String getLockFileName() {
        return this.lockFileName;
    }

    /**
     *
     * @return name of testapp
     */
    public String getAppName() {
        return this.getClass().getName();
    }

    /**
     *
     *  @return pid of java process running testapp
     */
    public long getPid() {
        if (appProcess == null) {
            throw new RuntimeException("Process is not alive");
        }
        return appProcess.getPid();
    }

    /**
     *
     * @return process object
     */
    public Process getProcess() {
        return appProcess;
    }

    /**
     *
     * @return application output as string array. Empty array if application produced no output
     */
    List<String> getAppOutput() {
        if (appProcess.isAlive()) {
            throw new RuntimeException("Process is still alive. Can't get its output.");
        }
        return storedAppOutput;
    }

    /* Make sure all part of the app use the same method to get dates,
     as different methods could produce different results
     */
    private static long epoch() {
        return new Date().getTime();
    }

    private static long lastModified(String fileName) throws IOException {
        Path path = Paths.get(fileName);
        BasicFileAttributes attr = Files.readAttributes(path, BasicFileAttributes.class);
        return attr.lastModifiedTime().toMillis();
    }

    private static void setLastModified(String fileName, long newTime) throws IOException {
        Path path = Paths.get(fileName);
        FileTime fileTime = FileTime.fromMillis(newTime);
        Files.setLastModifiedTime(path, fileTime);
    }

    /**
     * create lock
     *
     * @throws IOException
     */
    public void createLock() throws IOException {
        Path path = Paths.get(lockFileName);
        // Files.deleteIfExists(path);
        Files.createFile(path);
        lockCreationTime = lastModified(lockFileName);
    }

    /**
     * Delete lock
     *
     * @throws IOException
     */
    public void deleteLock() throws IOException {
        try {
            Path path = Paths.get(lockFileName);
            Files.delete(path);
        } catch (NoSuchFileException ex) {
            // Lock already deleted. Ignore error
        }
    }

    public void waitAppTerminate() {
        while (true) {
            try {
                appProcess.waitFor();
                break;
            } catch (InterruptedException ex) {
                // pass
            }
        }
    }

    /**
     * The app touches the lock file when it's started
     * wait while it happens. Caller have to delete lock on wait error.
     *
     * @param timeout
     * @throws java.io.IOException
     */
    public void waitAppReady(long timeout) throws IOException {
        long here = epoch();
        while (true) {
            long epoch = epoch();
            if (epoch - here > (timeout * 1000)) {
                throw new IOException("App waiting timeout");
            }

            // Live process should touch lock file every second
            long lm = lastModified(lockFileName);
            if (lm > lockCreationTime) {
                break;
            }

            // Make sure process didn't already exit
            if (!appProcess.isAlive()) {
                throw new IOException("App exited unexpectedly with " + appProcess.exitValue());
            }

            try {
                Thread.sleep(spinDelay);
            } catch (InterruptedException ex) {
                // pass
            }
        }
    }

    /**
     * Run the app
     *
     * @param vmArguments
     * @throws IOException
     */
    public void runApp(List<String> vmArguments)
            throws IOException {

        // We should always use testjava or throw an exception,
        // so we can't use JDKToolFinder.getJDKTool("java");
        // that falls back to compile java on error
        String jdkPath = System.getProperty("test.jdk");
        if (jdkPath == null) {
            // we are not under jtreg, try env
            Map<String, String> env = System.getenv();
            jdkPath = env.get("TESTJAVA");
        }

        if (jdkPath == null) {
            throw new RuntimeException("Can't determine jdk path neither test.jdk property no TESTJAVA env are set");
        }

        String osname = System.getProperty("os.name");
        String javapath = jdkPath + ((osname.startsWith("window")) ? "/bin/java.exe" : "/bin/java");

        List<String> cmd = new ArrayList();
        cmd.add(javapath);


        if (vmArguments == null) {
            // Propagate test.vm.options to LingeredApp, filter out possible empty options
            String testVmOpts[] = System.getProperty("test.vm.opts","").split("\\s+");
            for (String s : testVmOpts) {
                if (!s.equals("")) {
                    cmd.add(s);
                }
            }
        }
        else{
            // Lets user manage LingerApp options
            cmd.addAll(vmArguments);
        }

        // Make sure we set correct classpath to run the app
        cmd.add("-cp");
        String classpath = System.getProperty("test.class.path");
        cmd.add((classpath == null) ? "." : classpath);

        cmd.add(this.getAppName());
        cmd.add(lockFileName);

        // Reporting
        StringBuilder cmdLine = new StringBuilder();
        for (String strCmd : cmd) {
            cmdLine.append("'").append(strCmd).append("' ");
        }

        // A bit of verbosity
        System.out.println("Command line: [" + cmdLine.toString() + "]");

        ProcessBuilder pb = new ProcessBuilder(cmd);
        // we don't expect any error output but make sure we are not stuck on pipe
        // pb.redirectErrorStream(false);
        pb.redirectError(ProcessBuilder.Redirect.INHERIT);

        appProcess = pb.start();

        // Create pipe reader for process, and read stdin and stderr to array of strings
        InputGobbler gb = new InputGobbler(appProcess.getInputStream(), storedAppOutput);
        gb.start();
    }

    /**
     *  High level interface for test writers
     */
    /**
     * Factory method that creates SmartAppTest object with ready to use application
     * lock name is autogenerated, wait timeout is hardcoded
     * @param cmd - vm options, could be null to auto add testvm.options
     * @return LingeredApp object
     * @throws IOException
     */
    public static LingeredApp startApp(List<String> cmd) throws IOException {
        final String lockName = UUID.randomUUID().toString() + ".lck";
        final int waitTime = 10;

        LingeredApp a = new LingeredApp(lockName);
        a.createLock();
        try {
            a.runApp(cmd);
            a.waitAppReady(waitTime);
        } catch (Exception ex) {
            a.deleteLock();
            throw ex;
        }

        return a;
    }

    public static LingeredApp startApp() throws IOException {
        return startApp(null);
    }

    /**
     * Delete lock file that signal app to terminate, then
     * waits until app is actually terminated.
     * @throws IOException
     */
    public void stopApp() throws IOException {
        deleteLock();
        waitAppTerminate();
        int exitcode = appProcess.exitValue();
        if (exitcode != 0) {
            throw new IOException("LingeredApp terminated with non-zero exit code " + exitcode);
        }
    }

    /**
     * LastModified time might not work correctly in some cases it might
     * cause later failures
     */

    public static boolean isLastModifiedWorking() {
        boolean sane = true;
        try {
            long lm = lastModified(".");
            if (lm == 0) {
                System.err.println("SANITY Warning! The lastModifiedTime() doesn't work on this system, it returns 0");
                sane = false;
            }

            long now = epoch();
            if (lm > now) {
                System.err.println("SANITY Warning! The Clock is wrong on this system lastModifiedTime() > getTime()");
                sane = false;
            }

            setLastModified(".", epoch());
            long lm1 = lastModified(".");
            if (lm1 <= lm) {
                System.err.println("SANITY Warning! The setLastModified doesn't work on this system");
                sane = false;
            }
        }
        catch(IOException e) {
            System.err.println("SANITY Warning! IOException during sanity check " + e);
            sane = false;
        }

        return sane;
    }

    /**
     * This part is the application it self
     */
    public static void main(String args[]) {

        if (args.length != 1) {
            System.err.println("Lock file name is not specified");
            System.exit(7);
        }

        String theLockFileName = args[0];

        try {
            Path path = Paths.get(theLockFileName);

            while (Files.exists(path)) {
                // Touch the lock to indicate our readiness
                setLastModified(theLockFileName, epoch());
                Thread.sleep(spinDelay);
            }
        } catch (NoSuchFileException ex) {
            // Lock deleted while we are setting last modified time.
            // Ignore error and lets the app exits
        } catch (Exception ex) {
            System.err.println("LingeredApp ERROR: " + ex);
            // Leave exit_code = 1 to Java launcher
            System.exit(3);
        }

        System.exit(0);
    }
}
