// Copyright (C) 2009 The Android Open Source Project
//
// Licensed 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 com.google.gerrit.sshd;

import com.google.common.util.concurrent.Atomics;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.extensions.registration.DynamicItem;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.git.WorkQueue;
import com.google.gerrit.sshd.SshScope.Context;
import com.google.gwtorm.server.SchemaFactory;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.CommandFactory;
import org.apache.sshd.server.Environment;
import org.apache.sshd.server.ExitCallback;
import org.apache.sshd.server.SessionAware;
import org.apache.sshd.server.session.ServerSession;
import org.eclipse.jgit.lib.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/** Creates a CommandFactory using commands registered by {@link CommandModule}. */
@Singleton
class CommandFactoryProvider implements Provider<CommandFactory>, LifecycleListener {
  private static final Logger logger = LoggerFactory.getLogger(CommandFactoryProvider.class);

  private final DispatchCommandProvider dispatcher;
  private final SshLog log;
  private final SshScope sshScope;
  private final ScheduledExecutorService startExecutor;
  private final ExecutorService destroyExecutor;
  private final SchemaFactory<ReviewDb> schemaFactory;
  private final DynamicItem<SshCreateCommandInterceptor> createCommandInterceptor;

  @Inject
  CommandFactoryProvider(
      @CommandName(Commands.ROOT) DispatchCommandProvider d,
      @GerritServerConfig Config cfg,
      WorkQueue workQueue,
      SshLog l,
      SshScope s,
      SchemaFactory<ReviewDb> sf,
      DynamicItem<SshCreateCommandInterceptor> i) {
    dispatcher = d;
    log = l;
    sshScope = s;
    schemaFactory = sf;
    createCommandInterceptor = i;

    int threads = cfg.getInt("sshd", "commandStartThreads", 2);
    startExecutor = workQueue.createQueue(threads, "SshCommandStart", true);
    destroyExecutor =
        Executors.newSingleThreadExecutor(
            new ThreadFactoryBuilder()
                .setNameFormat("SshCommandDestroy-%s")
                .setDaemon(true)
                .build());
  }

  @Override
  public void start() {}

  @Override
  public void stop() {
    destroyExecutor.shutdownNow();
  }

  @Override
  public CommandFactory get() {
    return new CommandFactory() {
      @Override
      public Command createCommand(String requestCommand) {
        String c = requestCommand;
        SshCreateCommandInterceptor interceptor = createCommandInterceptor.get();
        if (interceptor != null) {
          c = interceptor.intercept(c);
        }
        return new Trampoline(c);
      }
    };
  }

  private class Trampoline implements Command, SessionAware {
    private final String commandLine;
    private final String[] argv;
    private InputStream in;
    private OutputStream out;
    private OutputStream err;
    private ExitCallback exit;
    private Environment env;
    private Context ctx;
    private DispatchCommand cmd;
    private final AtomicBoolean logged;
    private final AtomicReference<Future<?>> task;

    Trampoline(String cmdLine) {
      commandLine = cmdLine;
      argv = split(cmdLine);
      logged = new AtomicBoolean();
      task = Atomics.newReference();
    }

    @Override
    public void setInputStream(InputStream in) {
      this.in = in;
    }

    @Override
    public void setOutputStream(OutputStream out) {
      this.out = out;
    }

    @Override
    public void setErrorStream(OutputStream err) {
      this.err = err;
    }

    @Override
    public void setExitCallback(ExitCallback callback) {
      this.exit = callback;
    }

    @Override
    public void setSession(ServerSession session) {
      final SshSession s = session.getAttribute(SshSession.KEY);
      this.ctx = sshScope.newContext(schemaFactory, s, commandLine);
    }

    @Override
    public void start(Environment env) throws IOException {
      this.env = env;
      final Context ctx = this.ctx;
      task.set(
          startExecutor.submit(
              new Runnable() {
                @Override
                public void run() {
                  try {
                    onStart();
                  } catch (Exception e) {
                    logger.warn(
                        "Cannot start command \""
                            + ctx.getCommandLine()
                            + "\" for user "
                            + ctx.getSession().getUsername(),
                        e);
                  }
                }

                @Override
                public String toString() {
                  return "start (user " + ctx.getSession().getUsername() + ")";
                }
              }));
    }

    private void onStart() throws IOException {
      synchronized (this) {
        final Context old = sshScope.set(ctx);
        try {
          cmd = dispatcher.get();
          cmd.setArguments(argv);
          cmd.setInputStream(in);
          cmd.setOutputStream(out);
          cmd.setErrorStream(err);
          cmd.setExitCallback(
              new ExitCallback() {
                @Override
                public void onExit(int rc, String exitMessage) {
                  exit.onExit(translateExit(rc), exitMessage);
                  log(rc);
                }

                @Override
                public void onExit(int rc) {
                  exit.onExit(translateExit(rc));
                  log(rc);
                }
              });
          cmd.start(env);
        } finally {
          sshScope.set(old);
        }
      }
    }

    private int translateExit(int rc) {
      switch (rc) {
        case BaseCommand.STATUS_NOT_ADMIN:
          return 1;

        case BaseCommand.STATUS_CANCEL:
          return 15 /* SIGKILL */;

        case BaseCommand.STATUS_NOT_FOUND:
          return 127 /* POSIX not found */;

        default:
          return rc;
      }
    }

    private void log(int rc) {
      if (logged.compareAndSet(false, true)) {
        log.onExecute(cmd, rc, ctx.getSession());
      }
    }

    @Override
    public void destroy() {
      Future<?> future = task.getAndSet(null);
      if (future != null) {
        future.cancel(true);
        destroyExecutor.execute(this::onDestroy);
      }
    }

    private void onDestroy() {
      synchronized (this) {
        if (cmd != null) {
          final Context old = sshScope.set(ctx);
          try {
            cmd.destroy();
            log(BaseCommand.STATUS_CANCEL);
          } finally {
            ctx = null;
            cmd = null;
            sshScope.set(old);
          }
        }
      }
    }
  }

  /** Split a command line into a string array. */
  public static String[] split(String commandLine) {
    final List<String> list = new ArrayList<>();
    boolean inquote = false;
    boolean inDblQuote = false;
    StringBuilder r = new StringBuilder();
    for (int ip = 0; ip < commandLine.length(); ) {
      final char b = commandLine.charAt(ip++);
      switch (b) {
        case '\t':
        case ' ':
          if (inquote || inDblQuote) {
            r.append(b);
          } else if (r.length() > 0) {
            list.add(r.toString());
            r = new StringBuilder();
          }
          continue;
        case '\"':
          if (inquote) {
            r.append(b);
          } else {
            inDblQuote = !inDblQuote;
          }
          continue;
        case '\'':
          if (inDblQuote) {
            r.append(b);
          } else {
            inquote = !inquote;
          }
          continue;
        case '\\':
          if (inquote || ip == commandLine.length()) {
            r.append(b); // literal within a quote
          } else {
            r.append(commandLine.charAt(ip++));
          }
          continue;
        default:
          r.append(b);
          continue;
      }
    }
    if (r.length() > 0) {
      list.add(r.toString());
    }
    return list.toArray(new String[list.size()]);
  }
}
