// 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.server.config.GerritServerConfig;
import com.google.gerrit.server.git.WorkQueue;
import com.google.gerrit.sshd.SshScope.Context;
import com.google.inject.Inject;
import com.google.inject.Provider;

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;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
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;

/**
 * Creates a CommandFactory using commands registered by {@link CommandModule}.
 */
class CommandFactoryProvider implements Provider<CommandFactory> {
  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 Executor destroyExecutor;

  @Inject
  CommandFactoryProvider(
      @CommandName(Commands.ROOT) final DispatchCommandProvider d,
      @GerritServerConfig final Config cfg, final WorkQueue workQueue,
      final SshLog l, final SshScope s) {
    dispatcher = d;
    log = l;
    sshScope = s;

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

  @Override
  public CommandFactory get() {
    return new CommandFactory() {
      public Command createCommand(final String requestCommand) {
        return new Trampoline(requestCommand);
      }
    };
  }

  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(final String cmdLine) {
      commandLine = cmdLine;
      argv = split(cmdLine);
      logged = new AtomicBoolean();
      task = Atomics.newReference();
    }

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

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

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

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

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

    public void start(final Environment env) throws IOException {
      this.env = env;
      final Context ctx = this.ctx;
      task.set(startExecutor.submit(new Runnable() {
        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(final 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(final int rc) {
      if (logged.compareAndSet(false, true)) {
        log.onExecute(rc);
      }
    }

    @Override
    public void destroy() {
      Future<?> future = task.getAndSet(null);
      if (future != null) {
        future.cancel(true);
        destroyExecutor.execute(new Runnable() {
          @Override
          public void run() {
            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. */
  static public String[] split(String commandLine) {
    final List<String> list = new ArrayList<String>();
    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()]);
  }
}
