/*
 * 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.java.lsp.server.debugging.launch;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import org.eclipse.lsp4j.MessageParams;
import org.eclipse.lsp4j.MessageType;
import org.eclipse.lsp4j.debug.TerminatedEventArguments;

import org.eclipse.lsp4j.jsonrpc.ResponseErrorException;
import org.eclipse.lsp4j.jsonrpc.messages.ResponseError;
import org.eclipse.lsp4j.jsonrpc.messages.ResponseErrorCode;
import org.eclipse.lsp4j.services.LanguageClient;

import org.netbeans.api.annotations.common.CheckForNull;
import org.netbeans.api.annotations.common.NonNull;
import org.netbeans.api.annotations.common.NullAllowed;
import org.netbeans.api.debugger.DebuggerManager;
import org.netbeans.api.debugger.DebuggerManagerAdapter;
import org.netbeans.api.debugger.DebuggerManagerListener;
import org.netbeans.api.debugger.Session;
import org.netbeans.api.debugger.jpda.JPDADebugger;
import org.netbeans.api.extexecution.base.ExplicitProcessParameters;
import org.netbeans.api.extexecution.ExecutionDescriptor;
import org.netbeans.api.extexecution.ExecutionService;
import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.api.java.queries.UnitTestForSourceQuery;
import org.netbeans.api.project.FileOwnerQuery;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectUtils;
import org.netbeans.modules.java.lsp.server.Utils;
import org.netbeans.modules.java.lsp.server.debugging.DebugAdapterContext;
import org.netbeans.modules.java.lsp.server.debugging.NbSourceProvider;
import org.netbeans.modules.java.lsp.server.debugging.utils.ErrorUtilities;
import org.netbeans.modules.java.lsp.server.progress.OperationContext;
import org.netbeans.modules.java.lsp.server.progress.ProgressOperationEvent;
import org.netbeans.modules.java.lsp.server.progress.ProgressOperationListener;
import org.netbeans.modules.java.lsp.server.progress.TestProgressHandler;
import org.netbeans.modules.java.nativeimage.debugger.api.NIDebugRunner;
import org.netbeans.modules.nativeimage.api.debug.NIDebugger;
import org.netbeans.spi.project.ActionProgress;
import org.netbeans.spi.project.ActionProvider;
import org.netbeans.spi.project.ProjectConfiguration;
import org.netbeans.spi.project.ProjectConfigurationProvider;
import org.netbeans.spi.project.SingleMethod;

import org.openide.filesystems.FileObject;
import org.openide.util.BaseUtilities;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.Pair;
import org.openide.util.RequestProcessor;
import org.openide.util.lookup.Lookups;
import org.openide.util.lookup.ProxyLookup;

/**
 *
 * @author martin
 */
@NbBundle.Messages({
    "ERR_UnsupportedLaunchDebug=Debugging is not supported in this project.",
    "ERR_UnsupportedLaunch=Running  is not supported in this project.",
    "# {0} - the selected configuration",
    "# {1} - the suggested configuration",
    "ERR_UnsupportedLaunchDebugConfig=Debugging is not supported in configuration \"{0}\", please switch to {1}",
    "# {0} - the selected configuration",
    "# {1} - the suggested configuration",
    "ERR_UnsupportedLaunchConfig=Running is not supported in configuration \"{0}\", please switch to {1}.",
    "ERR_LaunchDefaultConfiguration=the default one.",
    "# {0} - the recommended configuration",
    "ERR_LaunchSupportiveConfigName=\"{0}\"",
})
public abstract class NbLaunchDelegate {

    private final RequestProcessor requestProcessor = new RequestProcessor(NbLaunchDelegate.class);
    private final Map<DebugAdapterContext, DebuggerManagerListener> debuggerListeners = new ConcurrentHashMap<>();

    public abstract void preLaunch(Map<String, Object> launchArguments, DebugAdapterContext context);

    public abstract void postLaunch(Map<String, Object> launchArguments, DebugAdapterContext context);
    
    protected void notifyFinished(DebugAdapterContext ctx, boolean success) {
        // Remove a possibly staled debugger listener
        DebuggerManagerListener listener = debuggerListeners.remove(ctx);
        if (listener != null) {
            DebuggerManager.getDebuggerManager().removeDebuggerListener(listener);
        }
    }

    public final CompletableFuture<Void> nbLaunch(FileObject toRun, File nativeImageFile, String method, Map<String, Object> launchArguments, DebugAdapterContext context, boolean debug, boolean testRun, Consumer<NbProcessConsole.ConsoleMessage> consoleMessages) {
        CompletableFuture<Void> launchFuture = new CompletableFuture<>();
        NbProcessConsole ioContext = new NbProcessConsole(consoleMessages);
        SingleMethod singleMethod;
        if (method != null) {
            singleMethod = new SingleMethod(toRun, method);
        } else {
            singleMethod = null;
        }
        ActionProgress progress = new ActionProgress() {
            private final AtomicInteger count = new AtomicInteger(0);
            private final AtomicBoolean finalSuccess = new AtomicBoolean(true);
            @Override
            protected void started() {
                count.incrementAndGet();
            }

            @Override
            public void finished(boolean success) {
                if (count.decrementAndGet() <= 0) {
                    ioContext.stop();
                    notifyFinished(context, success && finalSuccess.get());
                } else if (!success) {
                    finalSuccess.set(success);
                }
            }
        };
        if (toRun != null) {
            class W extends Writer {
                @Override
                public void write(char[] cbuf, int off, int len) throws IOException {
                    write(String.copyValueOf(cbuf, off, len));
                }

                @Override
                public void write(String str) throws IOException {
                    ioContext.stdIn(str);
                }

                @Override
                public void flush() throws IOException {
                    // nop 
                }

                @Override
                public void close() throws IOException {
                    // nop
                }
            }
            W writer = new W();
            CompletableFuture<Pair<ActionProvider, String>> commandFuture = findTargetWithPossibleRebuild(toRun, singleMethod, debug, testRun, ioContext);
            commandFuture.thenAccept((providerAndCommand) -> {
                List<String> args = argsToStringList(launchArguments.get("args"));
                List<String> vmArgs = argsToStringList(launchArguments.get("vmArgs"));
                ExplicitProcessParameters params = ExplicitProcessParameters.empty();
                if (!(args.isEmpty() && vmArgs.isEmpty())) {
                    ExplicitProcessParameters.Builder bld = ExplicitProcessParameters.builder();
                    bld.launcherArgs(vmArgs);
                    bld.args(args);
                    bld.replaceArgs(false);
                    params = bld.build();
                }
                OperationContext ctx = OperationContext.find(Lookup.getDefault());
                ctx.addProgressOperationListener(null, new ProgressOperationListener() {
                    @Override
                    public void progressHandleCreated(ProgressOperationEvent e) {
                        context.setProcessExecutorHandle(e.getProgressHandle());
                    }
                });
                TestProgressHandler testProgressHandler = ctx.getClient().getNbCodeCapabilities().hasTestResultsSupport() ? new TestProgressHandler(ctx.getClient(), context.getClient(), Utils.toUri(toRun)) : null;
                Lookup launchCtx = new ProxyLookup(
                        testProgressHandler != null ? Lookups.fixed(toRun, ioContext, progress, testProgressHandler) : Lookups.fixed(toRun, ioContext, progress),
                        Lookup.getDefault()
                );
                
                ProjectConfiguration selectConfiguration = null;
                ProjectConfigurationProvider<ProjectConfiguration> pcp = null;
                
                Object o = launchArguments.get("launchConfiguration");
                if (o instanceof String) {
                    Project p = FileOwnerQuery.getOwner(toRun);
                    if (p != null) {
                        pcp = p.getLookup().lookup(ProjectConfigurationProvider.class);
                        if (pcp != null) {
                            String n = (String)o;
                            selectConfiguration = pcp.getConfigurations().stream().filter(c -> n.equals(c.getDisplayName())).findAny().orElse(null);
                        }
                    }
                }
                List<? super Object> runContext = new ArrayList<>();
                runContext.add(toRun);
                runContext.add(params);
                runContext.add(ioContext);
                runContext.add(progress);
                
                Lookup lookup;
                if (singleMethod != null) {
                    runContext.add(singleMethod);
                }
                if (selectConfiguration != null) {
                    runContext.add(selectConfiguration);
                }
                
                lookup = Lookups.fixed(runContext.toArray(new Object[runContext.size()]));
                // the execution Lookup is fully populated now. If the Project supports Configurations,
                // check if the action is actually enabled in the prescribed configuration. If it is not, 
                if (pcp != null) {
                    final ActionProvider ap = providerAndCommand.first();
                    final String cmd = providerAndCommand.second();
                    if (!ap.isActionEnabled(cmd, lookup)) {
                        
                        // attempt to locate a different configuration that enables the action:
                        ProjectConfiguration supportive = null;
                        int confIndex = runContext.indexOf(selectConfiguration);
                        if (confIndex == -1) {
                            runContext.add(null);
                            confIndex = runContext.size() - 1;
                        }
                        boolean defConfig = true;
                        for (ProjectConfiguration c : pcp.getConfigurations()) {
                            runContext.set(confIndex, c);
                            Lookup tryConf = Lookups.fixed(runContext.toArray(new Object[runContext.size()]));
                            if (ap.isActionEnabled(cmd, tryConf)) {
                                supportive = c;
                                break;
                            }
                            defConfig = false;
                        }
                        String msg;
                        String recommended = defConfig ? Bundle.ERR_LaunchDefaultConfiguration(): Bundle.ERR_LaunchSupportiveConfigName(supportive.getDisplayName());
                        if (debug) {
                            msg = supportive == null ? 
                                 Bundle.ERR_UnsupportedLaunchDebug() : Bundle.ERR_UnsupportedLaunchDebugConfig(selectConfiguration.getDisplayName(),  recommended);
                        } else {
                            msg = supportive == null ? 
                                 Bundle.ERR_UnsupportedLaunch() : Bundle.ERR_UnsupportedLaunchConfig(selectConfiguration.getDisplayName(), recommended);
                        }
                        LanguageClient client = context.getLspSession().getLookup().lookup(LanguageClient.class);
                        if (client != null) {
                            client.showMessage(new MessageParams(MessageType.Warning, msg));
                            // first complete the future
                            launchFuture.complete(null);
                            // and then fake debuggee termination.
                            context.getClient().terminated(new TerminatedEventArguments());
                        } else {
                            launchFuture.completeExceptionally(new CancellationException());
                        }
                        return;
                    }
                }

                context.setInputSinkProvider(() -> writer);
                if (debug) {
                    DebuggerManagerListener listener = new DebuggerManagerAdapter() {
                        @Override
                        public void sessionAdded(Session session) {
                            JPDADebugger debugger = session.lookupFirst(null, JPDADebugger.class);
                            if (debugger != null) {
                                DebuggerManager.getDebuggerManager().removeDebuggerListener(this);
                                debuggerListeners.remove(context);
                                Map properties = session.lookupFirst(null, Map.class);
                                NbSourceProvider sourceProvider = context.getSourceProvider();
                                sourceProvider.setSourcePath(properties != null ? (ClassPath) properties.getOrDefault("sourcepath", ClassPath.EMPTY) : ClassPath.EMPTY);
                                debugger.addPropertyChangeListener(JPDADebugger.PROP_STATE, new PropertyChangeListener() {
                                    @Override
                                    public void propertyChange(PropertyChangeEvent evt) {
                                        int newState = (int) evt.getNewValue();
                                        if (newState == JPDADebugger.STATE_RUNNING) {
                                            debugger.removePropertyChangeListener(JPDADebugger.PROP_STATE, this);
                                            NbDebugSession debugSession = new NbDebugSession(session);
                                            context.setDebugSession(debugSession);
                                            launchFuture.complete(null);
                                            context.getConfigurationSemaphore().waitForConfigurationDone();
                                        }
                                    }
                                });
                            }
                        }
                    };
                    DebuggerManager.getDebuggerManager().addDebuggerListener(listener);
                    debuggerListeners.put(context, listener);
                }
                Lookups.executeWith(launchCtx, () -> {
                    providerAndCommand.first().invokeAction(providerAndCommand.second(), lookup);

                });
                if (!debug) {
                    launchFuture.complete(null);
                }
            }).exceptionally((t) -> {
                launchFuture.completeExceptionally(t);
                return null;
            });
        } else {
            ExecutionDescriptor executionDescriptor = new ExecutionDescriptor()
                    .showProgress(true)
                    .showSuspended(true)
                    .frontWindowOnError(true)
                    .controllable(true);
            Lookup launchCtx = new ProxyLookup(
                    Lookups.fixed(ioContext, progress),
                    Lookup.getDefault()
            );
            List<String> args = argsToStringList(launchArguments.get("args"));
            // Add session's lookup, it may override dialog displayer, etc.
            Lookup execLookup = new ProxyLookup(launchCtx, context.getLspSession().getLookup());
            if (debug) {
                requestProcessor.post(() -> {
                    ActionProgress debugProgress = ActionProgress.start(launchCtx);
                    ExecutionDescriptor ed = executionDescriptor.postExecution((@NullAllowed Integer exitCode) -> {
                        debugProgress.finished(exitCode != null && exitCode == 0);
                    });
                    Lookups.executeWith(execLookup, () -> {
                        String miDebugger = (String) launchArguments.get("miDebugger");
                        startNativeDebug(nativeImageFile, args, miDebugger, context, ed, launchFuture, debugProgress);
                    });
                });
            } else {
                ExecutionDescriptor ed = executionDescriptor.postExecution((@NullAllowed Integer exitCode) -> {
                    ioContext.stop();
                    notifyFinished(context, exitCode != null && exitCode == 0);
                });
                Lookups.executeWith(execLookup, () -> {
                    execNative(nativeImageFile, args, context, ed, launchFuture);
                });
            }
        }
        return launchFuture;
    }

    private static void execNative(File nativeImageFile, List<String> args, DebugAdapterContext context, ExecutionDescriptor executionDescriptor, CompletableFuture<Void> launchFuture) {
        ExecutionService.newService(() -> {
            launchFuture.complete(null);
            List<String> command = args.isEmpty() ? Collections.singletonList(nativeImageFile.getAbsolutePath()) : join(nativeImageFile.getAbsolutePath(), args);
            try {
                return new ProcessBuilder(command).start();
            } catch (IOException ex) {
                ErrorUtilities.completeExceptionally(launchFuture,
                    "Failed to run debuggee native image: " + ex.getLocalizedMessage(),
                    ResponseErrorCode.serverErrorStart);
                throw ex;
            }
        }, executionDescriptor, "Run - " + nativeImageFile.getName()).run();
    }

    private static List<String> join(String first, List<String> next) {
        List<String> joined = new ArrayList<>(next.size() + 1);
        joined.add(first);
        joined.addAll(next);
        return joined;
    }

    private static void startNativeDebug(File nativeImageFile, List<String> args, String miDebugger, DebugAdapterContext context, ExecutionDescriptor executionDescriptor, CompletableFuture<Void> launchFuture, ActionProgress debugProgress) {
        AtomicReference<NbDebugSession> debugSessionRef = new AtomicReference<>();
        NIDebugger niDebugger;
        try {
            niDebugger = NIDebugRunner.start(nativeImageFile, args, miDebugger, null, null, executionDescriptor, engine -> {
                Session session = engine.lookupFirst(null, Session.class);
                NbDebugSession debugSession = new NbDebugSession(session);
                debugSessionRef.set(debugSession);
                context.setDebugSession(debugSession);
                launchFuture.complete(null);
                context.getConfigurationSemaphore().waitForConfigurationDone();
            });
        } catch (IllegalStateException ex) {
            ErrorUtilities.completeExceptionally(launchFuture,
                "Failed to launch debuggee native image. " + ex.getLocalizedMessage(),
                ResponseErrorCode.serverErrorStart);
            debugProgress.finished(false);
            return ;
        }
        NbDebugSession debugSession = debugSessionRef.get();
        debugSession.setNIDebugger(niDebugger);
    }

    @NonNull
    private List<String> argsToStringList(Object o) {
        if (o == null) {
            return Collections.emptyList();
        }
        if (o instanceof List) {
            for (Object item : (List)o) {
                if (!(o instanceof String)) {
                    throw new IllegalArgumentException("Only string parameters expected");
                }
            }
            return (List<String>)o;
        } else if (o instanceof String) {
            List<String> res = new ArrayList<>();
            return Arrays.asList(BaseUtilities.parseParameters(o.toString()));
        } else {
            throw new IllegalArgumentException("Expected String or String list");
        }
    }
    
    private static CompletableFuture<Pair<ActionProvider, String>> findTargetWithPossibleRebuild(FileObject toRun, SingleMethod singleMethod, boolean debug, boolean testRun, NbProcessConsole ioContext) throws IllegalArgumentException {
        Pair<ActionProvider, String> providerAndCommand = findTarget(toRun, singleMethod, debug, testRun);
        if (providerAndCommand != null) {
            return CompletableFuture.completedFuture(providerAndCommand);
        }
        CompletableFuture<Pair<ActionProvider,String>> afterBuild = new CompletableFuture<>();
        class CheckBuildProgress extends ActionProgress {
            boolean running;

            @Override
            protected void started() {
                running = true;
            }

            @Override
            public void finished(boolean success) {
                if (success) {
                    Pair<ActionProvider, String> providerAndCommand = findTarget(toRun, singleMethod, debug, testRun);
                    if (providerAndCommand != null) {
                        afterBuild.complete(providerAndCommand);
                        return;
                    }
                }
                afterBuild.completeExceptionally(new ResponseErrorException(new ResponseError(
                        ResponseErrorCode.MethodNotFound,
                        "Cannot find " + (debug ? "debug" : "run") + " action!", null)));
            }
        };
        CheckBuildProgress progress = new CheckBuildProgress();
        Lookup launchCtx = new ProxyLookup(
            Lookups.fixed(
                toRun, ioContext, progress
            ), Lookup.getDefault()
        );

        Collection<ActionProvider> providers = findActionProviders(toRun);
        for (ActionProvider ap : providers) {
            if (ap.isActionEnabled(ActionProvider.COMMAND_BUILD, launchCtx)) {
                Lookups.executeWith(launchCtx, () -> {
                    ap.invokeAction(ActionProvider.COMMAND_BUILD, launchCtx);
                });
                break;
            }
        }
        if (!progress.running) {
            progress.finished(true);
        }
        return afterBuild;
    }

    protected static @CheckForNull Pair<ActionProvider, String> findTarget(FileObject toRun, SingleMethod singleMethod, boolean debug, boolean testRun) {
        ClassPath sourceCP = ClassPath.getClassPath(toRun, ClassPath.SOURCE);
        FileObject fileRoot = sourceCP != null ? sourceCP.findOwnerRoot(toRun) : null;
        boolean mainSource;
        if (fileRoot != null) {
            mainSource = UnitTestForSourceQuery.findUnitTests(fileRoot).length > 0;
        } else {
            mainSource = !testRun;
        }
        ActionProvider provider = null;
        String command = null;
        Collection<ActionProvider> actionProviders = findActionProviders(toRun);
        Lookup testLookup = Lookups.singleton(toRun);
        String[] actions;
        if (!mainSource && singleMethod != null) {
            actions = debug ? new String[] {SingleMethod.COMMAND_DEBUG_SINGLE_METHOD}
                            : new String[] {SingleMethod.COMMAND_RUN_SINGLE_METHOD};
        } else {
            actions = debug ? mainSource ? new String[] {ActionProvider.COMMAND_DEBUG_SINGLE}
                                         : new String[] {ActionProvider.COMMAND_DEBUG_TEST_SINGLE, ActionProvider.COMMAND_DEBUG_SINGLE}
                            : mainSource ? new String[] {ActionProvider.COMMAND_RUN_SINGLE}
                                         : new String[] {ActionProvider.COMMAND_TEST_SINGLE, ActionProvider.COMMAND_RUN_SINGLE};
        }

        for (String commandCandidate : actions) {
            provider = findActionProvider(commandCandidate, actionProviders, testLookup);
            if (provider != null) {
                command = commandCandidate;
                break;
            }
        }

        if (provider == null) {
            command = debug ? mainSource ? ActionProvider.COMMAND_DEBUG
                                         : ActionProvider.COMMAND_DEBUG // DEBUG_TEST is missing?
                            : mainSource ? ActionProvider.COMMAND_RUN
                                         : ActionProvider.COMMAND_TEST;
            provider = findActionProvider(command, actionProviders, testLookup);
            if (!mainSource) {
                final Collection<ActionProvider> nestedAPs = findNestedActionProviders(toRun, command, testLookup);
                if (!nestedAPs.isEmpty()) {
                    final String finalCommand = command;
                    final ActionProvider finalProvider = provider;
                    provider = new ActionProvider() {
                        @Override
                        public String[] getSupportedActions() {
                            return new String[] {finalCommand};
                        }

                        @Override
                        public boolean isActionEnabled(String command, Lookup context) throws IllegalArgumentException {
                            return finalCommand.equals(command);
                        }

                        @Override
                        public void invokeAction(String command, Lookup context) throws IllegalArgumentException {
                            if (finalCommand.equals(command)) {
                                if (finalProvider != null) {
                                    finalProvider.invokeAction(command, context);
                                }
                                for (ActionProvider nestedAP : nestedAPs) {
                                    nestedAP.invokeAction(command, context);
                                }
                            }
                        }
                    };
                }
            }
        }
        if (provider == null) {
            return null;
        }
        return Pair.of(provider, command);
    }

    private static Collection<ActionProvider> findActionProviders(FileObject toRun) {
        Collection<ActionProvider> actionProviders = new ArrayList<>();
        Project prj = FileOwnerQuery.getOwner(toRun);
        if (prj != null) {
            ActionProvider ap = prj.getLookup().lookup(ActionProvider.class);
            actionProviders.add(ap);
        }
        actionProviders.addAll(Lookup.getDefault().lookupAll(ActionProvider.class));
        return actionProviders;
    }

    private static boolean supportsAction(ActionProvider ap, String action) {
        for (String supportedAction : ap.getSupportedActions()) {
            if (supportedAction.equals(action)) {
                return true;
            }
        }
        return false;
    }

    private static ActionProvider findActionProvider(String action, Collection<ActionProvider> actionProviders, Lookup enabledOnLookup) {
        for (ActionProvider ap : actionProviders) {
            if (supportsAction(ap, action) && ap.isActionEnabled(action, enabledOnLookup)) {
                return ap;
            }
        }
        return null;
    }

    private static Collection<ActionProvider> findNestedActionProviders(FileObject toRun, String action, Lookup enabledOnLookup) {
        Collection<ActionProvider> actionProviders = new ArrayList<>();
        Project prj = FileOwnerQuery.getOwner(toRun);
        if (prj != null) {
            for (Project containedPrj : ProjectUtils.getContainedProjects(prj, true)) {
                ActionProvider ap = containedPrj.getLookup().lookup(ActionProvider.class);
                if (supportsAction(ap, action) && ap.isActionEnabled(action, enabledOnLookup)) {
                    actionProviders.add(ap);
                }
            }
        }
        return actionProviders;
    }
}
