// Copyright (C) 2010 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.commands;

import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.base.Supplier;
import com.google.gerrit.common.UserScopedEventListener;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.extensions.annotations.RequiresCapability;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.extensions.registration.RegistrationHandle;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.events.Event;
import com.google.gerrit.server.events.EventTypes;
import com.google.gerrit.server.events.ProjectNameKeySerializer;
import com.google.gerrit.server.events.SupplierSerializer;
import com.google.gerrit.server.git.WorkQueue;
import com.google.gerrit.server.git.WorkQueue.CancelableRunnable;
import com.google.gerrit.sshd.BaseCommand;
import com.google.gerrit.sshd.CommandMetaData;
import com.google.gerrit.sshd.StreamCommandExecutor;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.inject.Inject;

import org.apache.sshd.server.Environment;
import org.kohsuke.args4j.Option;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;

@RequiresCapability(GlobalCapability.STREAM_EVENTS)
@CommandMetaData(name = "stream-events", description = "Monitor events occurring in real time")
final class StreamEvents extends BaseCommand {
  private static final Logger log =
      LoggerFactory.getLogger(StreamEvents.class);

  /** Maximum number of events that may be queued up for each connection. */
  private static final int MAX_EVENTS = 128;

  /** Number of events to write before yielding off the thread. */
  private static final int BATCH_SIZE = 32;

  @Option(name = "--subscribe", aliases = {"-s"}, metaVar = "SUBSCRIBE",
      usage = "subscribe to specific stream-events")
  private List<String> subscribedToEvents = new ArrayList<>();

  @Inject
  private IdentifiedUser currentUser;

  @Inject
  private DynamicSet<UserScopedEventListener> eventListeners;

  @Inject
  @StreamCommandExecutor
  private WorkQueue.Executor pool;

  /** Queue of events to stream to the connected user. */
  private final LinkedBlockingQueue<Event> queue =
      new LinkedBlockingQueue<>(MAX_EVENTS);

  private Gson gson;

  private RegistrationHandle eventListenerRegistration;

  /** Special event to notify clients they missed other events. */
  private static final class DroppedOutputEvent extends Event {
    private static final String TYPE = "dropped-output";
    DroppedOutputEvent() {
      super(TYPE);
    }
  }

  static {
    EventTypes.register(DroppedOutputEvent.TYPE, DroppedOutputEvent.class);
  }

  private final CancelableRunnable writer = new CancelableRunnable() {
    @Override
    public void run() {
      writeEvents();
    }

    @Override
    public void cancel() {
      onExit(0);
    }

    @Override
    public String toString() {
      return "Stream Events (" + currentUser.getAccount().getUserName() + ")";
    }
  };

  /** True if {@link DroppedOutputEvent} needs to be sent. */
  private volatile boolean dropped;

  /** Lock to protect {@link #queue}, {@link #task}, {@link #done}. */
  private final Object taskLock = new Object();

  /** True if no more messages should be sent to the output. */
  private boolean done;

  /**
   * Currently scheduled task to spin out {@link #queue}.
   * <p>
   * This field is usually {@code null}, unless there is at least one object
   * present inside of {@link #queue} ready for delivery. Tasks are only started
   * when there are events to be sent.
   */
  private Future<?> task;

  private PrintWriter stdout;

  @Override
  public void start(final Environment env) throws IOException {
    try {
      parseCommandLine();
    } catch (UnloggedFailure e) {
      String msg = e.getMessage();
      if (!msg.endsWith("\n")) {
        msg += "\n";
      }
      err.write(msg.getBytes(UTF_8));
      err.flush();
      onExit(1);
      return;
    }

    stdout = toPrintWriter(out);
    eventListenerRegistration =
        eventListeners.add(new UserScopedEventListener() {
          @Override
          public void onEvent(final Event event) {
            if (subscribedToEvents.isEmpty()
                || subscribedToEvents.contains(event.getType())) {
              offer(event);
            }
          }

          @Override
          public CurrentUser getUser() {
            return currentUser;
          }
        });

    gson = new GsonBuilder()
        .registerTypeAdapter(Supplier.class, new SupplierSerializer())
        .registerTypeAdapter(
            Project.NameKey.class, new ProjectNameKeySerializer())
        .create();
  }

  @Override
  protected void onExit(final int rc) {
    eventListenerRegistration.remove();

    synchronized (taskLock) {
      done = true;
    }

    super.onExit(rc);
  }

  @Override
  public void destroy() {
    eventListenerRegistration.remove();

    final boolean exit;
    synchronized (taskLock) {
      if (task != null) {
        task.cancel(true);
        exit = false; // onExit will be invoked by the task cancellation.
      } else {
        exit = !done;
      }
      done = true;
    }
    if (exit) {
      onExit(0);
    }
  }

  private void offer(final Event event) {
    synchronized (taskLock) {
      if (!queue.offer(event)) {
        dropped = true;
      }

      if (task == null && !done) {
        task = pool.submit(writer);
      }
    }
  }

  private Event poll() {
    synchronized (taskLock) {
      Event event = queue.poll();
      if (event == null) {
        task = null;
      }
      return event;
    }
  }

  private void writeEvents() {
    int processed = 0;

    while (processed < BATCH_SIZE) {
      if (Thread.interrupted() || stdout.checkError()) {
        // The other side either requested a shutdown by calling our
        // destroy() above, or it closed the stream and is no longer
        // accepting output. Either way terminate this instance.
        //
        eventListenerRegistration.remove();
        flush();
        onExit(0);
        return;
      }

      if (dropped) {
        write(new DroppedOutputEvent());
        dropped = false;
      }

      final Event event = poll();
      if (event == null) {
        break;
      }

      write(event);
      processed++;
    }

    flush();

    if (BATCH_SIZE <= processed) {
      // We processed the limit, but more might remain in the queue.
      // Schedule the write task again so we will come back here and
      // can process more events.
      //
      synchronized (taskLock) {
        task = pool.submit(writer);
      }
    }
  }

  private void write(final Object message) {
    String msg = null;
    try {
      msg = gson.toJson(message) + "\n";
    } catch (Exception e) {
      log.warn("Could not deserialize the msg: ", e);
    }
    if (msg != null) {
      synchronized (stdout) {
        stdout.print(msg);
      }
    }
  }

  private void flush() {
    synchronized (stdout) {
      stdout.flush();
    }
  }
}
