/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.netbeans.lib.jshell.agent;

import jdk.jshell.spi.SPIResolutionException;
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 org.netbeans.lib.jshell.agent.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 {

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

    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();
            performCommand(cmd, in, out);
        }
    }
    
    protected void performCommand(int cmd, ObjectInputStream in, ObjectOutputStream out) throws IOException {
            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<String>(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  ex) {
                    handleLoadFailure(ex, out);
                } catch (ClassNotFoundException ex) {
                    handleLoadFailure(ex, out);
                } catch (ClassCastException ex) {
                    handleLoadFailure(ex, out);
                }
                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;
                }
                String methodName = in.readUTF();
                Method doitMethod;
                try {
                    //this.getClass().getModule().addExports(SPIResolutionException.class.getPackage().getName(), klass.getModule());
                    doitMethod = klass.getDeclaredMethod(methodName, new Class<?>[0]);
                    doitMethod.setAccessible(true);
                    Object res;
                    try {
                        clientCodeEnter();
                        res = doitMethod.invoke(null, new Object[0]);
                    } catch (InvocationTargetException ex) {
                        if (ex.getCause() instanceof ThreadDeath) {
                            expectingStop = false;
                            throw (ThreadDeath) 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 SPIResolutionException) {
                        out.writeInt(RESULT_CORRALLED);
                        out.writeInt(((SPIResolutionException) 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 ex) {
                    handleInvocationFailure(ex, out);
                } catch (IllegalAccessException ex) {
                    handleInvocationFailure(ex, out);
                } 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;
        }
    }
    
    private void handleLoadFailure(Throwable ex, ObjectOutputStream out) throws IOException {
        debug("*** Load failure: %s\n", ex);
        out.writeInt(RESULT_FAIL);
        out.writeUTF(ex.toString());
        out.flush();
    }
    
    private void handleInvocationFailure(Throwable ex, ObjectOutputStream out) throws IOException {
        debug("*** Invoke failure: %s -- %s\n", ex, ex.getCause());
        out.writeInt(RESULT_FAIL);
        out.writeUTF(ex.toString());
        out.flush();
    }
    
    protected void handleUnknownCommand(int cmd, ObjectInputStream i, ObjectOutputStream o) throws IOException {
        debug("*** Bad command code: %d\n", cmd);
    }

    // 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 "\"" + (String)value + "\"";
        } else if (value instanceof Character) {
            return "'" + value + "'";
        } else {
            return value.toString();
        }
    }

    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();
        }

    }
}
