/*
 * 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.modules.debugger.jpda.truffle;

import com.sun.jdi.ArrayReference;
import com.sun.jdi.ArrayType;
import com.sun.jdi.BooleanValue;
import com.sun.jdi.ByteValue;
import com.sun.jdi.ClassNotLoadedException;
import com.sun.jdi.ClassObjectReference;
import com.sun.jdi.ClassType;
import com.sun.jdi.Field;
import com.sun.jdi.IncompatibleThreadStateException;
import com.sun.jdi.InvalidTypeException;
import com.sun.jdi.InvocationException;
import com.sun.jdi.Method;
import com.sun.jdi.ObjectReference;
import com.sun.jdi.ReferenceType;
import com.sun.jdi.StringReference;
import com.sun.jdi.ThreadReference;
import com.sun.jdi.Value;
import com.sun.jdi.VirtualMachine;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyVetoException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.Lock;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.netbeans.api.debugger.DebuggerManager;
import org.netbeans.api.debugger.jpda.JPDADebugger;
import org.netbeans.api.debugger.jpda.JPDAThread;
import org.netbeans.api.debugger.jpda.MethodBreakpoint;
import org.netbeans.api.debugger.jpda.event.JPDABreakpointEvent;
import org.netbeans.api.debugger.jpda.event.JPDABreakpointListener;

import org.netbeans.modules.debugger.jpda.jdi.ArrayReferenceWrapper;
import org.netbeans.modules.debugger.jpda.jdi.ArrayTypeWrapper;
import org.netbeans.modules.debugger.jpda.jdi.ClassNotPreparedExceptionWrapper;
import org.netbeans.modules.debugger.jpda.jdi.ClassObjectReferenceWrapper;
import org.netbeans.modules.debugger.jpda.jdi.ClassTypeWrapper;
import org.netbeans.modules.debugger.jpda.jdi.IllegalThreadStateExceptionWrapper;
import org.netbeans.modules.debugger.jpda.jdi.InternalExceptionWrapper;
import org.netbeans.modules.debugger.jpda.jdi.ObjectCollectedExceptionWrapper;
import org.netbeans.modules.debugger.jpda.jdi.ObjectReferenceWrapper;
import org.netbeans.modules.debugger.jpda.jdi.ReferenceTypeWrapper;
import org.netbeans.modules.debugger.jpda.jdi.ThreadReferenceWrapper;
import org.netbeans.modules.debugger.jpda.jdi.UnsupportedOperationExceptionWrapper;
import org.netbeans.modules.debugger.jpda.jdi.VMDisconnectedExceptionWrapper;
import org.netbeans.modules.debugger.jpda.jdi.VirtualMachineWrapper;
import org.netbeans.modules.debugger.jpda.models.JPDAThreadImpl;

import org.openide.util.Exceptions;
import org.openide.util.RequestProcessor;
import org.openide.util.WeakSet;

/**
 * Upload backend classed to the JVM.
 */
public final class RemoteServices {
    
    private static final Logger logger = Logger.getLogger(RemoteServices.class.getName());
    
    static final String REMOTE_CLASSES_ZIPFILE = "/org/netbeans/modules/debugger/jpda/truffle/resources/JPDATruffleBackend.jar";
    
    private static final Map<JPDADebugger, ClassObjectReference> remoteServiceClasses = new WeakHashMap<>();
    private static final Map<JPDADebugger, ThreadReference> remoteServiceAccess = new WeakHashMap<>();
    
    private static final RequestProcessor AUTORESUME_AFTER_SUSPEND_RP = new RequestProcessor("Autoresume after suspend", 1);
    
    private static final Set<PropertyChangeListener> serviceListeners = new WeakSet<>();

    private RemoteServices() {}
    
    public static void addServiceListener(PropertyChangeListener listener) {
        synchronized (serviceListeners) {
            serviceListeners.add(listener);
        }
    }

    private static void fireServiceClass(JPDADebugger debugger) {
        PropertyChangeEvent pche = new PropertyChangeEvent(RemoteServices.class, "serviceClass", null, debugger);
        PropertyChangeListener[] listeners;
        synchronized (serviceListeners) {
            listeners = serviceListeners.toArray(new PropertyChangeListener[]{});
        }
        for (PropertyChangeListener l : listeners) {
            l.propertyChange(pche);
        }
    }
    
    private static ObjectReference getTruffleClassLoader(ThreadReference tawt, VirtualMachine vm) throws InvalidTypeException, ClassNotLoadedException, IncompatibleThreadStateException, InvocationException, IOException, PropertyVetoException, InternalExceptionWrapper, VMDisconnectedExceptionWrapper, ObjectCollectedExceptionWrapper, UnsupportedOperationExceptionWrapper, ClassNotPreparedExceptionWrapper {
        /* Use:
           com.oracle.truffle.api.impl.TruffleLocator.class.getClassLoader()
        */
        ClassType truffleLocatorClass = getClass(vm, "com.oracle.truffle.api.impl.TruffleLocator");
        return truffleLocatorClass.classLoader();
    }
    
    private static ObjectReference getBootstrapClassLoader(ThreadReference tawt, VirtualMachine vm) throws InvalidTypeException, ClassNotLoadedException, IncompatibleThreadStateException, InvocationException, IOException, PropertyVetoException, InternalExceptionWrapper, VMDisconnectedExceptionWrapper, ObjectCollectedExceptionWrapper, UnsupportedOperationExceptionWrapper, ClassNotPreparedExceptionWrapper {
        /* Run this code:
            ClassLoader cl = ClassLoader.getSystemClassLoader();
            ClassLoader bcl;
            do {
                bcl = cl;
                cl = cl.getParent();
            } while (cl != null);
            return bcl;
         */
        ClassType classLoaderClass = getClass(vm, ClassLoader.class.getName());
        Method getSystemClassLoader = ClassTypeWrapper.concreteMethodByName(classLoaderClass, "getSystemClassLoader", "()Ljava/lang/ClassLoader;");
        ObjectReference cl = (ObjectReference) ClassTypeWrapper.invokeMethod(classLoaderClass, tawt, getSystemClassLoader, Collections.emptyList(), ObjectReference.INVOKE_SINGLE_THREADED);
        Method getParent = ClassTypeWrapper.concreteMethodByName(classLoaderClass, "getParent", "()Ljava/lang/ClassLoader;");
        ObjectReference bcl;
        do {
            bcl = cl;
            if ("sun.misc.Launcher$AppClassLoader".equals(cl.referenceType().name())) {     // NOI18N
                break;
            }
            cl = (ObjectReference) ObjectReferenceWrapper.invokeMethod(cl, tawt, getParent, Collections.emptyList(), ObjectReference.INVOKE_SINGLE_THREADED);
        } while (cl != null);
        return bcl;
    }
    
    private static ObjectReference getContextClassLoader(ThreadReference tawt, VirtualMachine vm) throws InvalidTypeException, ClassNotLoadedException, IncompatibleThreadStateException, InvocationException, IOException, PropertyVetoException, InternalExceptionWrapper, VMDisconnectedExceptionWrapper, ObjectCollectedExceptionWrapper, UnsupportedOperationExceptionWrapper, ClassNotPreparedExceptionWrapper {
        ReferenceType threadType = tawt.referenceType();
        Method getContextCl = ClassTypeWrapper.concreteMethodByName((ClassType) threadType, "getContextClassLoader", "()Ljava/lang/ClassLoader;");
        ObjectReference cl = (ObjectReference) ObjectReferenceWrapper.invokeMethod(tawt, tawt, getContextCl, Collections.emptyList(), ObjectReference.INVOKE_SINGLE_THREADED);
        ClassType classLoaderClass = null;
        if (cl == null) {
            classLoaderClass = getClass(vm, ClassLoader.class.getName());
            Method getSystemClassLoader = ClassTypeWrapper.concreteMethodByName(classLoaderClass, "getSystemClassLoader", "()Ljava/lang/ClassLoader;");
            cl = (ObjectReference) ClassTypeWrapper.invokeMethod(classLoaderClass, tawt, getSystemClassLoader, Collections.emptyList(), ObjectReference.INVOKE_SINGLE_THREADED);
        }
        return cl;
    }
    
    public static ClassObjectReference uploadBasicClasses(JPDAThreadImpl t, String basicClassName) throws InvalidTypeException, ClassNotLoadedException, IncompatibleThreadStateException, InvocationException, IOException, PropertyVetoException, InternalExceptionWrapper, VMDisconnectedExceptionWrapper, ObjectCollectedExceptionWrapper, UnsupportedOperationExceptionWrapper, ClassNotPreparedExceptionWrapper {
        ThreadReference tawt = t.getThreadReference();
        VirtualMachine vm = tawt.virtualMachine();
        
        t.notifyMethodInvoking();
        try {
            ClassObjectReference basicClass = null;
            t.accessLock.writeLock().lock();
            try {
                List<RemoteClass> remoteClasses = getRemoteClasses();
                for (RemoteClass rc : remoteClasses) {
                    String className = rc.name;
                    if (basicClass == null && className.endsWith(basicClassName) && className.indexOf('$') < 0) {
                        List<ReferenceType> classesByName = VirtualMachineWrapper.classesByName(vm, className);
                        if (!classesByName.isEmpty()) {
                            basicClass = ReferenceTypeWrapper.classObject(classesByName.get(0));
                        }
                        break;
                    }
                }
                // Suppose that when there's the basic class loaded, there are all.
                if (basicClass == null) {  // Load the classes only if there's not the basic one.
                    ObjectReference cl;
                    cl = getTruffleClassLoader(tawt, vm);
                    if (cl == null) {
                        cl = getBootstrapClassLoader(tawt, vm);
                    }
                    if (cl == null) {
                        cl = getContextClassLoader(tawt, vm);
                    }
                    ClassType classLoaderClass = (ClassType) ObjectReferenceWrapper.referenceType(cl);

                    ByteValue[] mirrorBytesCache = new ByteValue[256];
                    for (RemoteClass rc : remoteClasses) {
                        String className = rc.name;
                        ClassObjectReference theUploadedClass;
                        ArrayReference byteArray = createTargetBytes(vm, rc.bytes, mirrorBytesCache);
                        StringReference nameMirror = null;
                        try {
                            Method defineClass = ClassTypeWrapper.concreteMethodByName(classLoaderClass, "defineClass", "(Ljava/lang/String;[BII)Ljava/lang/Class;");
                            boolean uploaded = false;
                            while (!uploaded) {
                                nameMirror = VirtualMachineWrapper.mirrorOf(vm, className);
                                try {
                                    ObjectReferenceWrapper.disableCollection(nameMirror);
                                    uploaded = true;
                                } catch (ObjectCollectedExceptionWrapper ocex) {
                                    // Just collected, try again...
                                }
                            }
                            uploaded = false;
                            while (!uploaded) {
                                theUploadedClass = (ClassObjectReference) ObjectReferenceWrapper.invokeMethod(cl, tawt, defineClass, Arrays.asList(nameMirror, byteArray, vm.mirrorOf(0), vm.mirrorOf(rc.bytes.length)), ObjectReference.INVOKE_SINGLE_THREADED);
                                if (basicClass == null && rc.name.indexOf('$') < 0 && rc.name.endsWith("Accessor")) {
                                    try {
                                        // Disable collection only of the basic class
                                        ObjectReferenceWrapper.disableCollection(theUploadedClass);
                                        basicClass = theUploadedClass;
                                        uploaded = true;
                                    } catch (ObjectCollectedExceptionWrapper ocex) {
                                        // Just collected, try again...
                                    }
                                } else {
                                    uploaded = true;
                                }
                            }
                        } finally {
                            ObjectReferenceWrapper.enableCollection(byteArray); // We can dispose it now
                            if (nameMirror != null) {
                                ObjectReferenceWrapper.enableCollection(nameMirror);
                            }
                        }
                        //Method resolveClass = classLoaderClass.concreteMethodByName("resolveClass", "(Ljava/lang/Class;)V");
                        //systemClassLoader.invokeMethod(tawt, resolveClass, Arrays.asList(theUploadedClass), ObjectReference.INVOKE_SINGLE_THREADED);
                    }
                }
                if (basicClass != null) {
                    // Initialize the class:
                    ClassType theClass = getClass(vm, Class.class.getName());
                    // Perhaps it's not 100% correct, we should be calling the new class' newInstance() method, not Class.newInstance() method.
                    Method newInstance = ClassTypeWrapper.concreteMethodByName(theClass, "newInstance", "()Ljava/lang/Object;");
                    ObjectReference newInstanceOfBasicClass = (ObjectReference) ObjectReferenceWrapper.invokeMethod(basicClass, tawt, newInstance, Collections.emptyList(), ObjectReference.INVOKE_SINGLE_THREADED);
                }
            } finally {
                t.accessLock.writeLock().unlock();
            }
            if (basicClass != null) {
                synchronized (remoteServiceClasses) {
                    remoteServiceClasses.put(t.getDebugger(), basicClass);
                    t.getDebugger().addPropertyChangeListener(new RemoteServiceDebuggerListener());
                }
                fireServiceClass(t.getDebugger());
            }
            return basicClass;
        } finally {
            t.notifyMethodInvokeDone();
        }
    }
    
    private static void runOnBreakpoint(final JPDAThread awtThread, String bpClass, String bpMethod, final Runnable runnable, final CountDownLatch latch) {
        final MethodBreakpoint mb = MethodBreakpoint.create(bpClass, bpMethod);
        final JPDADebugger dbg = ((JPDAThreadImpl)awtThread).getDebugger();
        final PropertyChangeListener[] listenerPtr = new PropertyChangeListener[] { null };
        
        mb.setBreakpointType(MethodBreakpoint.TYPE_METHOD_ENTRY);
        mb.setSuspend(MethodBreakpoint.SUSPEND_EVENT_THREAD);
        mb.setHidden(true);
        mb.setThreadFilters(dbg, new JPDAThread[] { awtThread });
        mb.addJPDABreakpointListener(new JPDABreakpointListener() {
            @Override
            public void breakpointReached(JPDABreakpointEvent event) {
                if (dbg.equals(event.getDebugger())) {
                    try {
                        DebuggerManager.getDebuggerManager().removeBreakpoint(mb);
                        //System.err.println("BREAKPOINT "+mb+" REMOVED after reached."+" ID = "+System.identityHashCode(mb));
                        PropertyChangeListener listener = listenerPtr[0];
                        if (listener != null) {
                            dbg.removePropertyChangeListener(JPDADebugger.PROP_STATE, listener);
                            listenerPtr[0] = null;
                        }
                        try {
                            ((JPDAThreadImpl)awtThread).notifyMethodInvoking();
                            runnable.run();
                        } catch (PropertyVetoException e) {
                        } finally {
                            ((JPDAThreadImpl)awtThread).notifyMethodInvokeDone();
                        }
                    } finally {
                        event.resume();
                        latch.countDown();
                    }
                }
            }
        });
        PropertyChangeListener listener = new PropertyChangeListener() {
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                if (dbg.getState() == JPDADebugger.STATE_DISCONNECTED) {
                    DebuggerManager.getDebuggerManager().removeBreakpoint(mb);
                    //System.err.println("BREAKPOINT "+mb+" REMOVED after debugger finished."+" ID = "+System.identityHashCode(mb));
                    dbg.removePropertyChangeListener(JPDADebugger.PROP_STATE, this);
                    listenerPtr[0] = null;
                    latch.countDown();
                }
            }
        };
        dbg.addPropertyChangeListener(JPDADebugger.PROP_STATE, listener);
        listenerPtr[0] = listener;
        if (dbg.getState() != JPDADebugger.STATE_DISCONNECTED) {
            DebuggerManager.getDebuggerManager().addBreakpoint(mb);
            //System.err.println("ADD BP: "+mb+" ID = "+System.identityHashCode(mb));
        } else {
            dbg.removePropertyChangeListener(JPDADebugger.PROP_STATE, listener);
            //System.err.println("NOT ADDED BP: "+mb+" ID = "+System.identityHashCode(mb));
            latch.countDown();
        }
    }
    
    private static final Map<JPDAThread, RequestProcessor.Task> tasksByThreads = new WeakHashMap<JPDAThread, RequestProcessor.Task> ();
    
    /**
     * Run the provided runnable after the thread is assured to be stopped on an event.
     * If the thread was initially running, it's resumed with some delay
     * (to allow another execution of runOnStoppedThread() without the expensive thread preparation).
     * It's assumed that the runnable will invoke methods on the thread.
     * Therefore method invoke notification methods are executed automatically.
     * @param thread The remote thread.
     * @param run The Runnable that is executed when the thread is assured to be stopped on an event.
     * @throws PropertyVetoException when can not invoke methods.
     */
    public static void runOnStoppedThread(JPDAThread thread, final Runnable run) throws PropertyVetoException {
        final JPDAThreadImpl t = (JPDAThreadImpl) thread;
        
        Lock lock = t.accessLock.writeLock();
        lock.lock();
        try {
            ThreadReference threadReference = t.getThreadReference();
            boolean wasSuspended = t.isSuspended();
            if (t.isSuspended() && !threadReference.isAtBreakpoint()) {
                // TODO: Suspended, but will not be able to invoke methods
                
            }
            if (!t.isSuspended()) {
                final CountDownLatch latch = new CountDownLatch(1);
                lock.unlock();
                lock = null;
                VirtualMachine vm = ((JPDAThreadImpl) thread).getThreadReference().virtualMachine();
                ClassObjectReference serviceClassObject;
                synchronized (remoteServiceClasses) {
                    serviceClassObject = remoteServiceClasses.get(((JPDAThreadImpl) thread).getDebugger());
                }
                if (serviceClassObject == null) {
                    // The debugger session has finished already, do not run anything.
                    return ;
                }
                runOnBreakpoint(
                    thread, 
                    "org.netbeans.modules.debugger.jpda.visual.remote.RemoteAWTService", // NOI18N
                    "calledInAWT", // NOI18N
                    run,
                    latch
                );
                try {
                    ClassType serviceClass = (ClassType) ClassObjectReferenceWrapper.reflectedType(serviceClassObject);//getClass(vm, "org.netbeans.modules.debugger.jpda.visual.remote.RemoteService");
                    Field awtAccess = ReferenceTypeWrapper.fieldByName(serviceClass, "awtAccess"); // NOI18N
                    ClassTypeWrapper.setValue(serviceClass, awtAccess, VirtualMachineWrapper.mirrorOf(vm, true));
                } catch (InternalExceptionWrapper iex) {
                } catch (VMDisconnectedExceptionWrapper vmdex) {
                } catch (Exception ex) {
                    Exceptions.printStackTrace(ex);
                }
                try {
                    // wait for the async operation to finish
                    latch.await();
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            } else {
                RequestProcessor.Task autoresumeTask;
                if (!wasSuspended) {
                    AutoresumeTask resumeTask = new AutoresumeTask(t);
                    autoresumeTask = AUTORESUME_AFTER_SUSPEND_RP.create(resumeTask);
                    synchronized (tasksByThreads) {
                        tasksByThreads.put(thread, autoresumeTask);
                    }
                } else {
                    synchronized (tasksByThreads) {
                        autoresumeTask = tasksByThreads.get(thread);
                    }
                }
                t.notifyMethodInvoking();
                if (autoresumeTask != null) {
                    autoresumeTask.schedule(Integer.MAX_VALUE); // wait for run.run() to finish...
                }
                try {
                    run.run();
                } finally {
                    t.notifyMethodInvokeDone();
                    if (autoresumeTask != null) {
                        autoresumeTask.schedule(AutoresumeTask.WAIT_TIME);
                    }
                }
            }
        } finally {
            if (lock != null) {
                lock.unlock();
            }
        }
    }
    
    private static final Map<JPDADebugger, LoggingListeners> loggingListeners =
            new WeakHashMap<JPDADebugger, LoggingListeners>();
    
    private static final class LoggingListeners {
        
        private final Map<ObjectReference, Map<ClassObjectReference, Set<LoggingListenerCallBack>>> componentListeners =
                new HashMap<ObjectReference, Map<ClassObjectReference, Set<LoggingListenerCallBack>>>();
        
        static LoggingListeners get(JPDADebugger dbg) {
            synchronized (loggingListeners) {
                return loggingListeners.get(dbg);
            }
        }

        private synchronized boolean add(ObjectReference component, ClassObjectReference listenerClass, LoggingListenerCallBack listener) {
            Map<ClassObjectReference, Set<LoggingListenerCallBack>> listeners = componentListeners.get(component);
            if (listeners == null) {
                listeners = new HashMap<ClassObjectReference, Set<LoggingListenerCallBack>>();
                componentListeners.put(component, listeners);
            }
            Set<LoggingListenerCallBack> lcb = listeners.get(listenerClass);
            if (lcb == null) {
                lcb = new HashSet<LoggingListenerCallBack>();
                listeners.put(listenerClass, lcb);
            }
            return lcb.add(listener);
        }
        
        private synchronized boolean remove(ObjectReference component, ClassObjectReference listenerClass, LoggingListenerCallBack listener) {
            Map<ClassObjectReference, Set<LoggingListenerCallBack>> listeners = componentListeners.get(component);
            if (listeners == null) {
                return false;
            }
            Set<LoggingListenerCallBack> lcb = listeners.get(listenerClass);
            if (lcb == null) {
                return false;
            }
            boolean removed = lcb.remove(listener);
            if (removed) {
                if (lcb.isEmpty()) {
                    listeners.remove(listenerClass);
                    if (listeners.isEmpty()) {
                        componentListeners.remove(component);
                    }
                }
            }
            return removed;
        }
        
        synchronized Set<LoggingListenerCallBack> getListeners(ObjectReference component, ClassObjectReference listenerClass) {
            Map<ClassObjectReference, Set<LoggingListenerCallBack>> listeners = componentListeners.get(component);
            if (listeners == null) {
                return null;
            }
            return listeners.get(listenerClass);
        }
        
        private synchronized boolean isEmpty() {
            return componentListeners.isEmpty();
        }
        
    }
    
    static void setAccessLoopStarted(JPDADebugger debugger, ThreadReference accessThread) {
        synchronized (remoteServiceAccess) {
            remoteServiceAccess.put(debugger, accessThread);
        }
        fireServiceClass(debugger);
    }
    
    public static boolean interruptServiceAccessThread(JPDADebugger debugger) {
        ClassObjectReference serviceClass = getServiceClass(debugger);
        if (serviceClass != null) {
            ThreadReference accessThread;
            synchronized (remoteServiceAccess) {
                accessThread = remoteServiceAccess.get(debugger);
            }
            if (accessThread == null) {
                return false;
            }
            logger.fine("RemoteServices.interruptServiceAccessThread()");
            try {
                ClassType serviceClassType = (ClassType) ClassObjectReferenceWrapper.reflectedType(serviceClass);
                Field accessLoopSleepingField = ReferenceTypeWrapper.fieldByName(serviceClassType, "accessLoopSleeping");
                synchronized (accessThread) {
                    boolean isSleeping;
                    int repeatCheck = 10;
                    do {
                        BooleanValue sleepingValue = (BooleanValue) serviceClassType.getValue(accessLoopSleepingField);
                        isSleeping = sleepingValue.booleanValue();
                        if (isSleeping || --repeatCheck < 0) {
                            break;
                        } else {
                            try {
                                Thread.sleep(100);
                            } catch (InterruptedException iex) {}
                        }
                        logger.log(Level.FINE, "  isSleeping = {0}", isSleeping);
                    } while (!isSleeping);
                    if (isSleeping) {
                        ThreadReferenceWrapper.interrupt(accessThread);
                        //System.err.println("  INTERRUPTED.");
                        return true;
                    }
                }
            } catch (InternalExceptionWrapper |
                     VMDisconnectedExceptionWrapper |
                     ObjectCollectedExceptionWrapper |
                     ClassNotPreparedExceptionWrapper |
                     IllegalThreadStateExceptionWrapper ex) {
                logger.log(Level.FINE, "  NOT interrupted: ", ex);
            }
            logger.fine("  NOT Interrupted.");
        }
        return false;
    }
    
    public static ClassObjectReference getServiceClass(JPDADebugger debugger) {
        synchronized (remoteServiceClasses) {
            return remoteServiceClasses.get(debugger);
        }
        
    }
    
    static ClassType getClass(VirtualMachine vm, String name) throws InternalExceptionWrapper, VMDisconnectedExceptionWrapper, ObjectCollectedExceptionWrapper {
        List<ReferenceType> classList = VirtualMachineWrapper.classesByName(vm, name);
        ReferenceType clazz = null;
        for (ReferenceType c : classList) {
            if (ReferenceTypeWrapper.classLoader(c) == null) {
                clazz = c;
                break;
            }
        }
        if (clazz == null && classList.size() > 0) {
            clazz = classList.get(0);
        }
        return (ClassType) clazz;
    }
    
    static ArrayType getArrayClass(VirtualMachine vm, String name) throws InternalExceptionWrapper, VMDisconnectedExceptionWrapper, ObjectCollectedExceptionWrapper {
        List<ReferenceType> classList = VirtualMachineWrapper.classesByName(vm, name);
        ReferenceType clazz = null;
        for (ReferenceType c : classList) {
            if (ReferenceTypeWrapper.classLoader(c) == null) {
                clazz = c;
                break;
            }
        }
        return (ArrayType) clazz;
    }
    
    private static List<RemoteClass> getRemoteClasses() throws IOException {
        InputStream in = openRemoteClasses();
        try {
            ZipInputStream zin = new ZipInputStream(in);
            ZipEntry ze;
            List<RemoteClass> rcl = new ArrayList<RemoteClass>();
            while((ze = zin.getNextEntry()) != null) {
                String fileName = ze.getName();
                if (!fileName.endsWith(".class")) {
                    continue;
                }
                String name = fileName.substring(0, fileName.length() - ".class".length());
                int baseStart = name.lastIndexOf('/');
                if (baseStart < 0) {
                    continue;
                }
                /*baseStart++;
                int baseEnd = name.indexOf('$', baseStart);
                if (baseEnd < 0) {
                    baseEnd = name.length();
                }*/
                RemoteClass rc = new RemoteClass();
                rc.name = name.replace('/', '.');
                int l = (int) ze.getSize();
                byte[] bytes = new byte[l];
                int num = 0;
                while (num < l) {
                    int r = zin.read(bytes, num, l - num);
                    if (r < 0) {
                        Exceptions.printStackTrace(new IllegalStateException("Can not read full content of "+name+" entry. Length = "+l+", read num = "+num));
                        break;
                    }
                    num += r;
                }
                rc.bytes = bytes;
                rcl.add(rc);
            }
            return rcl;
        } finally {
            in.close();
        }
    }

    static InputStream openRemoteClasses() {
        return RemoteServices.class.getResourceAsStream(REMOTE_CLASSES_ZIPFILE);
    }
    
    private static ArrayReference createTargetBytes(VirtualMachine vm, byte[] bytes,
                                                    ByteValue[] mirrorBytesCache) throws InvalidTypeException,
                                                                                         ClassNotLoadedException,
                                                                                         InternalExceptionWrapper,
                                                                                         VMDisconnectedExceptionWrapper,
                                                                                         ObjectCollectedExceptionWrapper,
                                                                                         UnsupportedOperationExceptionWrapper {
        ArrayType bytesArrayClass = getArrayClass(vm, "byte[]");
        ArrayReference array = null;
        boolean disabledCollection = false;
        while (!disabledCollection) {
            array = ArrayTypeWrapper.newInstance(bytesArrayClass, bytes.length);
            try {
                ObjectReferenceWrapper.disableCollection(array);
                disabledCollection = true;
            } catch (ObjectCollectedExceptionWrapper ocex) {
                // Collected too soon, try again...
            }
        }
        List<Value> values = new ArrayList<Value>(bytes.length);
        for (int i = 0; i < bytes.length; i++) {
            byte b = bytes[i];
            ByteValue mb = mirrorBytesCache[128 + b];
            if (mb == null) {
                mb = VirtualMachineWrapper.mirrorOf(vm, b);
                mirrorBytesCache[128 + b] = mb;
            }
            values.add(mb);
        }
        ArrayReferenceWrapper.setValues(array, values);
        return array;
    }
    
    private static class RemoteServiceDebuggerListener implements PropertyChangeListener {

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            if (JPDADebugger.PROP_STATE.equals(evt.getPropertyName())) {
                JPDADebugger d = (JPDADebugger) evt.getSource();
                if (JPDADebugger.STATE_DISCONNECTED == d.getState()) {
                    d.removePropertyChangeListener(this);
                    synchronized (remoteServiceClasses) {
                        remoteServiceClasses.remove(d);
                    }
                }
            }
        }
        
    }
    
    private static class RemoteClass {
        private String name;
        private byte[] bytes;
    }
    
    public static class RemoteListener {
        
        private String type;
        private List<String> allTypesList;
        private String[] allTypes;
        //private String classType;
        private ObjectReference l;
        
        public RemoteListener(String type, ObjectReference l) {
            this.type = type;
            this.l = l;
        }
        
        public String getType() {
            return type;
        }
        
        public void setAllTypes(String[] allTypes) {
            this.allTypes = allTypes;
        }
        
        private void addType(String listenerType) {
            if (allTypesList == null) {
                allTypesList = new ArrayList<String>();
                allTypesList.add(type);
            }
            allTypesList.add(listenerType);
        }
        
        public String[] getTypes() {
            if (allTypes == null) {
                if (allTypesList != null) {
                    allTypes = allTypesList.toArray(new String[] {});
                } else {
                    allTypes = new String[] { type };
                }
            }
            return allTypes;
        }
        
        //public String getClassType() {
        //    return classType;
        //}
        
        public ObjectReference getListener() {
            return l;
        }

        @Override
        public String toString() {
            return "RemoteListener("+type+")["+l+"]";
        }

    }
    
    public static interface LoggingListenerCallBack {
        
        public void eventsData(String[] data, String[] stack);
        
    }
    
    private static class AutoresumeTask implements Runnable, PropertyChangeListener {
        
        private static final int WAIT_TIME = 500;
        
        private volatile JPDAThreadImpl t;

        public AutoresumeTask(JPDAThreadImpl t) {
            this.t = t;
            t.addPropertyChangeListener(this);
        }

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            JPDAThreadImpl thread = this.t;
            if (thread == null) {
                return ;
            }
            if (JPDAThread.PROP_SUSPENDED.equals(evt.getPropertyName()) &&
                !"methodInvoke".equals(evt.getPropagationId())) {               // NOI18N
                
                thread.removePropertyChangeListener(this);
                logger.fine("AutoresumeTask: autoresume canceled, thread changed suspended state: suspended = "+thread.isSuspended());
                synchronized (tasksByThreads) {
                    tasksByThreads.remove(thread);
                }
                t = null;
            }
        }
        
        @Override
        public void run() {
            JPDAThreadImpl thread = this.t;
            this.t = null;
            if (thread != null) {
                thread.removePropertyChangeListener(this);
                thread.resume();
            }
        }
    }

}
