/*
 * Copyright (c) 2014, 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.  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 jdk.internal.jshell.remote;
import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.Socket;

import java.util.ArrayList;
import java.util.List;

import static jdk.internal.jshell.remote.RemoteCodes.*;

import java.util.Map;
import java.util.TreeMap;

/**
 * The remote agent runs in the execution process (separate from the main JShell
 * process.  This agent loads code over a socket from the main JShell process,
 * executes the code, and other misc,
 * @author Robert Field
 */
class RemoteAgent {

    private final RemoteClassLoader loader = new RemoteClassLoader();
    private final Map<String, Class<?>> klasses = new TreeMap<>();

    public static void main(String[] args) throws Exception {
        String loopBack = null;
        Socket socket = new Socket(loopBack, Integer.parseInt(args[0]));
        (new RemoteAgent()).commandLoop(socket);
    }

    void commandLoop(Socket socket) throws IOException {
        // in before out -- so we don't hang the controlling process
        ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
        OutputStream socketOut = socket.getOutputStream();
        System.setOut(new PrintStream(new MultiplexingOutputStream("out", socketOut), true));
        System.setErr(new PrintStream(new MultiplexingOutputStream("err", socketOut), true));
        ObjectOutputStream out = new ObjectOutputStream(new MultiplexingOutputStream("command", socketOut));
        while (true) {
            int cmd = in.readInt();
            switch (cmd) {
                case CMD_EXIT:
                    // Terminate this process
                    return;
                case CMD_LOAD:
                    // Load a generated class file over the wire
                    try {
                        int count = in.readInt();
                        List<String> names = new ArrayList<>(count);
                        for (int i = 0; i < count; ++i) {
                            String name = in.readUTF();
                            byte[] kb = (byte[]) in.readObject();
                            loader.delare(name, kb);
                            names.add(name);
                        }
                        for (String name : names) {
                            Class<?> klass = loader.loadClass(name);
                            klasses.put(name, klass);
                            // Get class loaded to the point of, at least, preparation
                            klass.getDeclaredMethods();
                        }
                        out.writeInt(RESULT_SUCCESS);
                        out.flush();
                    } catch (IOException | ClassNotFoundException | ClassCastException ex) {
                        debug("*** Load failure: %s\n", ex);
                        out.writeInt(RESULT_FAIL);
                        out.writeUTF(ex.toString());
                        out.flush();
                    }
                    break;
                case CMD_INVOKE: {
                    // Invoke executable entry point in loaded code
                    String name = in.readUTF();
                    Class<?> klass = klasses.get(name);
                    if (klass == null) {
                        debug("*** Invoke failure: no such class loaded %s\n", name);
                        out.writeInt(RESULT_FAIL);
                        out.writeUTF("no such class loaded: " + name);
                        out.flush();
                        break;
                    }
                    Method doitMethod;
                    try {
                        this.getClass().getModule().addExports(RemoteResolutionException.class.getPackage().getName(), klass.getModule());
                        doitMethod = klass.getDeclaredMethod(DOIT_METHOD_NAME, new Class<?>[0]);
                        doitMethod.setAccessible(true);
                        Object res;
                        try {
                            clientCodeEnter();
                            res = doitMethod.invoke(null, new Object[0]);
                        } catch (InvocationTargetException ex) {
                            if (ex.getCause() instanceof StopExecutionException) {
                                expectingStop = false;
                                throw (StopExecutionException) ex.getCause();
                            }
                            throw ex;
                        } catch (StopExecutionException ex) {
                            expectingStop = false;
                            throw ex;
                        } finally {
                            clientCodeLeave();
                        }
                        out.writeInt(RESULT_SUCCESS);
                        out.writeUTF(valueString(res));
                        out.flush();
                    } catch (InvocationTargetException ex) {
                        Throwable cause = ex.getCause();
                        StackTraceElement[] elems = cause.getStackTrace();
                        if (cause instanceof RemoteResolutionException) {
                            out.writeInt(RESULT_CORRALLED);
                            out.writeInt(((RemoteResolutionException) cause).id);
                        } else {
                            out.writeInt(RESULT_EXCEPTION);
                            out.writeUTF(cause.getClass().getName());
                            out.writeUTF(cause.getMessage() == null ? "<none>" : cause.getMessage());
                        }
                        out.writeInt(elems.length);
                        for (StackTraceElement ste : elems) {
                            out.writeUTF(ste.getClassName());
                            out.writeUTF(ste.getMethodName());
                            out.writeUTF(ste.getFileName() == null ? "<none>" : ste.getFileName());
                            out.writeInt(ste.getLineNumber());
                        }
                        out.flush();
                    } catch (NoSuchMethodException | IllegalAccessException ex) {
                        debug("*** Invoke failure: %s -- %s\n", ex, ex.getCause());
                        out.writeInt(RESULT_FAIL);
                        out.writeUTF(ex.toString());
                        out.flush();
                    } catch (StopExecutionException ex) {
                        try {
                            out.writeInt(RESULT_KILLED);
                            out.flush();
                        } catch (IOException err) {
                            debug("*** Error writing killed result: %s -- %s\n", ex, ex.getCause());
                        }
                    }
                    System.out.flush();
                    break;
                }
                case CMD_VARVALUE: {
                    // Retrieve a variable value
                    String classname = in.readUTF();
                    String varname = in.readUTF();
                    Class<?> klass = klasses.get(classname);
                    if (klass == null) {
                        debug("*** Var value failure: no such class loaded %s\n", classname);
                        out.writeInt(RESULT_FAIL);
                        out.writeUTF("no such class loaded: " + classname);
                        out.flush();
                        break;
                    }
                    try {
                        Field var = klass.getDeclaredField(varname);
                        var.setAccessible(true);
                        Object res = var.get(null);
                        out.writeInt(RESULT_SUCCESS);
                        out.writeUTF(valueString(res));
                        out.flush();
                    } catch (Exception ex) {
                        debug("*** Var value failure: no such field %s.%s\n", classname, varname);
                        out.writeInt(RESULT_FAIL);
                        out.writeUTF("no such field loaded: " + varname + " in class: " + classname);
                        out.flush();
                    }
                    break;
                }
                case CMD_CLASSPATH: {
                    // Append to the claspath
                    String cp = in.readUTF();
                    for (String path : cp.split(File.pathSeparator)) {
                        loader.addURL(new File(path).toURI().toURL());
                    }
                    out.writeInt(RESULT_SUCCESS);
                    out.flush();
                    break;
                }
                default:
                    debug("*** Bad command code: %d\n", cmd);
                    break;
            }
        }
    }

    // These three variables are used by the main JShell process in interrupting
    // the running process.  Access is via JDI, so the reference is not visible
    // to code inspection.
    private boolean inClientCode; // Queried by the main process
    private boolean expectingStop; // Set by the main process

    // thrown by the main process via JDI:
    private final StopExecutionException stopException = new StopExecutionException();

    @SuppressWarnings("serial")             // serialVersionUID intentionally omitted
    private class StopExecutionException extends ThreadDeath {
        @Override public synchronized Throwable fillInStackTrace() {
            return this;
        }
    }

    void clientCodeEnter() {
        expectingStop = false;
        inClientCode = true;
    }

    void clientCodeLeave() {
        inClientCode = false;
        while (expectingStop) {
            try {
                Thread.sleep(0);
            } catch (InterruptedException ex) {
                debug("*** Sleep interrupted while waiting for stop exception: %s\n", ex);
            }
        }
    }

    private void debug(String format, Object... args) {
        System.err.printf("REMOTE: "+format, args);
    }

    static String valueString(Object value) {
        if (value == null) {
            return "null";
        } else if (value instanceof String) {
            return "\"" + expunge((String)value) + "\"";
        } else if (value instanceof Character) {
            return "'" + value + "'";
        } else {
            return expunge(value.toString());
        }
    }

    /**
     * Expunge internal info from string
     * @param s string to process
     * @return string the display, JShell package and wrapper class names removed
     */
    static String expunge(String s) {
        StringBuilder sb = new StringBuilder();
        for (String comp : PREFIX_PATTERN.split(s)) {
            sb.append(comp);
        }
        return sb.toString();
    }

    private static final class MultiplexingOutputStream extends OutputStream {

        private static final int PACKET_SIZE = 127;

        private final byte[] name;
        private final OutputStream delegate;

        public MultiplexingOutputStream(String name, OutputStream delegate) {
            try {
                this.name = name.getBytes("UTF-8");
                this.delegate = delegate;
            } catch (UnsupportedEncodingException ex) {
                throw new IllegalStateException(ex); //should not happen
            }
        }

        @Override
        public void write(int b) throws IOException {
            synchronized (delegate) {
                delegate.write(name.length); //assuming the len is small enough to fit into byte
                delegate.write(name);
                delegate.write(1);
                delegate.write(b);
                delegate.flush();
            }
        }

        @Override
        public void write(byte[] b, int off, int len) throws IOException {
            synchronized (delegate) {
                int i = 0;
                while (len > 0) {
                    int size = Math.min(PACKET_SIZE, len);

                    delegate.write(name.length); //assuming the len is small enough to fit into byte
                    delegate.write(name);
                    delegate.write(size);
                    delegate.write(b, off + i, size);
                    i += size;
                    len -= size;
                }

                delegate.flush();
            }
        }

        @Override
        public void flush() throws IOException {
            super.flush();
            delegate.flush();
        }

        @Override
        public void close() throws IOException {
            super.close();
            delegate.close();
        }

    }
}
