/*
 * 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.BooleanValue;
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.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.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Lock;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.netbeans.api.debugger.jpda.JPDAClassType;
import org.netbeans.api.debugger.jpda.JPDADebugger;
import org.netbeans.api.debugger.jpda.JPDAThread;
import org.netbeans.modules.debugger.jpda.JPDADebuggerImpl;
import org.netbeans.modules.debugger.jpda.expr.InvocationExceptionTranslated;
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.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.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.netbeans.modules.debugger.jpda.truffle.access.TruffleAccess;
import static org.netbeans.modules.debugger.jpda.truffle.access.TruffleAccess.BASIC_CLASS_NAME;
import org.netbeans.modules.debugger.jpda.truffle.breakpoints.TruffleBreakpointsHandler;
import org.netbeans.modules.debugger.jpda.truffle.options.TruffleOptions;
import org.netbeans.modules.javascript2.debug.breakpoints.JSLineBreakpoint;
import org.openide.util.Exceptions;

/**
 * Handles remote JPDATruffleDebugManager.
 */
final class DebugManagerHandler {
    
    private static final Logger LOG = Logger.getLogger(DebugManagerHandler.class.getName());
    
    private static final String ACCESSOR_START_ACCESS_LOOP = "startAccessLoop"; // NOI18N
    private static final String ACCESSOR_LOOP_RUNNING_FIELD = "accessLoopRunning";  // NOI18N
    private static final String ACCESSOR_SET_UP_DEBUG_MANAGER_FOR = "setUpDebugManagerFor"; // NOI18N
    private static final String ACCESSOR_SET_UP_DEBUG_MANAGER_FOR_SGN =
            "(L"+Object.class.getName().replace('.', '/')+";ZZ)"+                // NOI18N
            "Lorg/netbeans/modules/debugger/jpda/backend/truffle/JPDATruffleDebugManager;"; // NOI18N
    private static final String ACCESSOR_SET_INCLUDE_INTERNAL = "setIncludeInternal"; // NOI18N
    private static final String ACCESSOR_SET_INCLUDE_INTERNAL_SGN = "(Z)V"; // NOI18N
    
    private static final Map<JPDADebugger, Boolean> dbgStepInto = Collections.synchronizedMap(new WeakHashMap<JPDADebugger, Boolean>());

    private final JPDADebugger debugger;
    private final AtomicBoolean inited = new AtomicBoolean(false);
    private ClassType accessorClass;
    private JPDAClassType accessorJPDAClass;
    private final Object accessorClassLock = new Object();
    //private ObjectReference debugManager;
    private final TruffleBreakpointsHandler breakpointsHandler;
    private final PropertyChangeListener optionsChangeListener = new OptionsChangeListener();
    
    public DebugManagerHandler(JPDADebugger debugger) {
        this.debugger = debugger;
        this.breakpointsHandler = new TruffleBreakpointsHandler(debugger);
        TruffleOptions.onLanguageDeveloperModeChange(optionsChangeListener);
    }
    
    static void execStepInto(JPDADebugger debugger, boolean doStepInto) {
        if (doStepInto) {
            dbgStepInto.put(debugger, doStepInto);
        } else {
            dbgStepInto.remove(debugger);
        }
    }
    
    private boolean isStepInto() {
        Boolean stepInto = dbgStepInto.get(debugger);
        return stepInto != null && stepInto;
    }
    
    void newPolyglotEngineInstance(ObjectReference engine, JPDAThreadImpl thread) {
        LOG.log(Level.FINE, "Engine created breakpoint hit: engine = {0} in thread = {1}", new Object[] { engine, thread.getThreadReference()});
        if (inited.compareAndSet(false, true)) {
            initDebuggerRemoteService(thread);
        }
        if (accessorClass == null) {
            // No accessor
            return ;
        }
        InvocationExceptionTranslated iextr = null;
        try {
            // Create an instance of JPDATruffleDebugManager in the backend
            // and submit breakpoints:
            thread.notifyMethodInvoking();
            VirtualMachine vm = ((JPDADebuggerImpl) debugger).getVirtualMachine();
            if (vm == null) {
                return ;
            }
            BooleanValue includeInternal = vm.mirrorOf(TruffleOptions.isLanguageDeveloperMode());
            BooleanValue doStepInto = vm.mirrorOf(isStepInto());
            Method debugManagerMethod = ClassTypeWrapper.concreteMethodByName(
                    accessorClass,
                    ACCESSOR_SET_UP_DEBUG_MANAGER_FOR,
                    ACCESSOR_SET_UP_DEBUG_MANAGER_FOR_SGN);
            ThreadReference tr = thread.getThreadReference();
            List<Value> dmArgs = Arrays.asList(engine, includeInternal, doStepInto);
            LOG.log(Level.FINE, "Setting engine and step into = {0}", isStepInto());
            Object ret = ClassTypeWrapper.invokeMethod(accessorClass, tr, debugManagerMethod, dmArgs, ObjectReference.INVOKE_SINGLE_THREADED);
            if (ret instanceof ObjectReference) {   // Can be null when an existing debug manager is reused.
                //debugManager = (ObjectReference) ret;
                breakpointsHandler.submitBreakpoints(accessorClass, (ObjectReference) ret, thread);
            }
        } catch (VMDisconnectedExceptionWrapper vmd) {
        } catch (InvocationException iex) {
            iextr = new InvocationExceptionTranslated(iex, thread.getDebugger());
            Exceptions.printStackTrace(iex);
        } catch (Exception ex) {
            Exceptions.printStackTrace(ex);
        } finally {
            thread.notifyMethodInvokeDone();
        }
        if (iextr != null) {
            iextr.preload(thread);
            Exceptions.printStackTrace(iextr);
        }
    }

    private void initDebuggerRemoteService(JPDAThread thread) {
        if (LOG.isLoggable(Level.FINE)) {
            LOG.log(Level.FINE, "initDebuggerRemoteService({0})", thread);
        }
        JPDAThreadImpl t = (JPDAThreadImpl) thread;
        Lock writeLock = t.accessLock.writeLock();
        writeLock.lock();
        try {
            ClassObjectReference cor = null;
            try {
                cor = RemoteServices.uploadBasicClasses(t, BASIC_CLASS_NAME);
            } catch (PropertyVetoException |
                     InvalidTypeException |
                     ClassNotLoadedException |
                     IncompatibleThreadStateException |
                     IOException pvex) {
                Exceptions.printStackTrace(pvex);
            } catch (InvocationException ex) {
                Exceptions.printStackTrace(ex);
                final InvocationExceptionTranslated iextr = new InvocationExceptionTranslated(ex, t.getDebugger());
                iextr.preload(t);
                Exceptions.printStackTrace(iextr);
            }
            if (LOG.isLoggable(Level.FINE)) {
                LOG.log(Level.FINE, "Uploaded class = {0}", cor);
            }
            if (cor == null) {
                return ;
            }
            ThreadReference tr = t.getThreadReference();
            
            ClassType serviceClass = (ClassType) ClassObjectReferenceWrapper.reflectedType(cor);//RemoteServices.getClass(vm, "org.netbeans.modules.debugger.jpda.visual.remote.RemoteService");

            InvocationExceptionTranslated iextr = null;
            Method startMethod = ClassTypeWrapper.concreteMethodByName(serviceClass, ACCESSOR_START_ACCESS_LOOP, "()Ljava/lang/Thread;");
            if (startMethod == null) {
                LOG.log(Level.WARNING, "Could not start the access loop of "+serviceClass+", no "+ACCESSOR_START_ACCESS_LOOP+" method.");
                return ;
            }
            try {
                t.notifyMethodInvoking();
                Value ret = ClassTypeWrapper.invokeMethod(serviceClass, tr, startMethod, Collections.emptyList(), ObjectReference.INVOKE_SINGLE_THREADED);
                if (ret instanceof ThreadReference) {
                    RemoteServices.setAccessLoopStarted(t.getDebugger(), (ThreadReference) ret);
                } else {
                    LOG.log(Level.WARNING, "Could not start the access loop of "+serviceClass);
                    return ;
                }
                TruffleAccess.assureBPSet(debugger, serviceClass);
                JPDAClassType serviceJPDAClass = ((JPDADebuggerImpl) debugger).getClassType(serviceClass);
                synchronized (accessorClassLock) {
                    accessorClass = serviceClass;
                    accessorJPDAClass = serviceJPDAClass;
                }
            } catch (InvocationException iex) {
                iextr = new InvocationExceptionTranslated(iex, t.getDebugger());
                Exceptions.printStackTrace(iex);
            } catch (ClassNotLoadedException |
                     IncompatibleThreadStateException |
                     InvalidTypeException |
                     PropertyVetoException |
                     InternalExceptionWrapper |
                     ObjectCollectedExceptionWrapper ex) {
                Exceptions.printStackTrace(ex);
            } finally {
                t.notifyMethodInvokeDone();
                ObjectReferenceWrapper.enableCollection(cor);
            }
            if (iextr != null) {
                iextr.preload(t);
                Exceptions.printStackTrace(iextr);
            }
        } catch (InternalExceptionWrapper iex) {
        } catch (ClassNotPreparedExceptionWrapper cnpex) {
            Exceptions.printStackTrace(cnpex);
        } catch (ObjectCollectedExceptionWrapper collex) {
        } catch (UnsupportedOperationExceptionWrapper uex) {
            LOG.log(Level.INFO, uex.getLocalizedMessage(), uex);
        } catch (VMDisconnectedExceptionWrapper vmd) {
        } finally {
            writeLock.unlock();
        }
        if (LOG.isLoggable(Level.FINE)) {
            try {
                LOG.fine("The JPDATruffleAccessor is there: "+
                            RemoteServices.getClass(t.getThreadReference().virtualMachine(),
                         BASIC_CLASS_NAME));
            } catch (Exception ex) {
                LOG.log(Level.FINE, "", ex);
            }
        }
    }
    
    ClassType getAccessorClass() {
        synchronized (accessorClassLock) {
            return accessorClass;
        }
    }
    
    JPDAClassType getAccessorJPDAClass() {
        synchronized (accessorClassLock) {
            return accessorJPDAClass;
        }
    }
    
    void destroy() {
        breakpointsHandler.destroy();
        if (accessorClass == null) {
            return ;
        }
        try {
            Field accessLoopRunning = ReferenceTypeWrapper.fieldByName(accessorClass, ACCESSOR_LOOP_RUNNING_FIELD);
            if (accessLoopRunning != null) {
                ClassTypeWrapper.setValue(accessorClass, accessLoopRunning,
                                          VirtualMachineWrapper.mirrorOf(accessorClass.virtualMachine(), false));
                RemoteServices.interruptServiceAccessThread(debugger);
            }
        } catch (VMDisconnectedExceptionWrapper vdex) {
            // Ignore
        } catch (Exception ex) {
            Exceptions.printStackTrace(ex);
        }
    }
    
    void breakpointAdded(JSLineBreakpoint jsLineBreakpoint) {
        breakpointsHandler.breakpointAdded(jsLineBreakpoint);
    }

    void breakpointRemoved(JSLineBreakpoint jsLineBreakpoint) {
        breakpointsHandler.breakpointRemoved(jsLineBreakpoint);
    }

    private final class OptionsChangeListener implements PropertyChangeListener {

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            if (accessorClass == null) {
                // No accessor
                return ;
            }
            if (TruffleOptions.PROPERTY_LANG_DEV_MODE.equals(evt.getPropertyName())) {
                JPDADebuggerImpl debuggerImpl = (JPDADebuggerImpl) debugger;
                debuggerImpl.getRequestProcessor().post(() -> {
                    VirtualMachine vm = debuggerImpl.getVirtualMachine();
                    if (vm == null) {
                        return ;
                    }
                    BooleanValue includeInternal = vm.mirrorOf(TruffleOptions.isLanguageDeveloperMode());
                    try {
                        Method debugManagerMethod = ClassTypeWrapper.concreteMethodByName(
                                accessorClass,
                                ACCESSOR_SET_INCLUDE_INTERNAL,
                                ACCESSOR_SET_INCLUDE_INTERNAL_SGN);
                        TruffleAccess.methodCallingAccess(debugger, new TruffleAccess.MethodCallsAccess() {
                            @Override
                            public void callMethods(JPDAThread thread) throws InvocationException {
                                ThreadReference tr = ((JPDAThreadImpl) thread).getThreadReference();
                                List<Value> dmArgs = Arrays.asList(includeInternal);
                                LOG.log(Level.FINE, "Setting includeInternal to {0}", includeInternal.value());
                                try {
                                    ClassTypeWrapper.invokeMethod(accessorClass, tr, debugManagerMethod, dmArgs, ObjectReference.INVOKE_SINGLE_THREADED);
                                } catch (Exception ex) {
                                    Exceptions.printStackTrace(ex);
                                }
                            }
                        });
                    } catch (ClassNotPreparedExceptionWrapper | InternalExceptionWrapper | VMDisconnectedExceptionWrapper ex) {
                        Exceptions.printStackTrace(ex);
                    }
                });
            }
        }
        
    }
}
