// 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.commands;

import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.git.TaskInfoFactory;
import com.google.gerrit.server.git.WorkQueue;
import com.google.gerrit.server.git.WorkQueue.ProjectTask;
import com.google.gerrit.server.git.WorkQueue.Task;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.util.IdGenerator;
import com.google.gerrit.sshd.AdminHighPriorityCommand;
import com.google.gerrit.sshd.CommandMetaData;
import com.google.gerrit.sshd.SshCommand;
import com.google.inject.Inject;

import org.apache.sshd.server.Environment;
import org.kohsuke.args4j.Option;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/** Display the current work queue. */
@AdminHighPriorityCommand
@CommandMetaData(name = "show-queue", descr = "Display the background work queues, including replication")
final class ShowQueue extends SshCommand {
  @Option(name = "-w", usage = "display without line width truncation")
  private boolean wide;

  @Inject
  private WorkQueue workQueue;

  @Inject
  private ProjectCache projectCache;

  @Inject
  private IdentifiedUser currentUser;

  private int columns = 80;
  private int taskNameWidth;

  @Override
  public void start(final Environment env) throws IOException {
    String s = env.getEnv().get(Environment.ENV_COLUMNS);
    if (s != null && !s.isEmpty()) {
      try {
        columns = Integer.parseInt(s);
      } catch (NumberFormatException err) {
        columns = 80;
      }
    }
    super.start(env);
  }

  @Override
  protected void run() {
    taskNameWidth = wide ? Integer.MAX_VALUE : columns - 8 - 12 - 8 - 4;
    final List<QueueTaskInfo> pending = getSortedTaskInfoList();

    stdout.print(String.format("%-8s %-12s %-8s %s\n",
        "Task", "State", "", "Command"));
    stdout.print("----------------------------------------------"
        + "--------------------------------\n");

    int numberOfPendingTasks = 0;
    final long now = System.currentTimeMillis();
    final boolean viewAll = currentUser.getCapabilities().canViewQueue();

    for (final QueueTaskInfo taskInfo : pending) {
      final long delay = taskInfo.delayMillis;
      final Task.State state = taskInfo.state;

      final String start;
      switch (state) {
        case DONE:
        case CANCELLED:
        case RUNNING:
        case READY:
          start = format(state);
          break;
        default:
          start = time(now, delay);
          break;
      }

      boolean regularUserCanSee = false;
      boolean hasCustomizedPrint = true;

      // If the user is not administrator, check if has rights to see
      // the Task
      Project.NameKey projectName = null;
      String remoteName = null;

      if (!viewAll) {
        projectName = taskInfo.getProjectNameKey();
        remoteName = taskInfo.getRemoteName();
        hasCustomizedPrint = taskInfo.hasCustomizedPrint();

        ProjectState e = null;
        if (projectName != null) {
          e = projectCache.get(projectName);
        }

        regularUserCanSee = e != null && e.controlFor(currentUser).isVisible();

        if (regularUserCanSee) {
          numberOfPendingTasks++;
        }
      }

      // Shows information about tasks depending on the user rights
      if (viewAll || (!hasCustomizedPrint && regularUserCanSee)) {
        stdout.print(String.format(
            "%8s %-12s %-8s %s\n",
            id(taskInfo.getTaskId()), start, "",
            taskInfo.getTaskString(taskNameWidth)));
      } else if (regularUserCanSee) {
        if (remoteName == null) {
          remoteName = projectName.get();
        } else {
          remoteName = remoteName + "/" + projectName;
        }

        stdout.print(String.format("%8s %-12s %-8s %s\n",
            id(taskInfo.getTaskId()), start, "", remoteName));
      }
    }
    stdout.print("----------------------------------------------"
        + "--------------------------------\n");

    if (viewAll) {
      numberOfPendingTasks = pending.size();
    }

    stdout.print("  " + numberOfPendingTasks + " tasks\n");
  }

  private List<QueueTaskInfo> getSortedTaskInfoList() {
    final List<QueueTaskInfo> taskInfos =
        workQueue.getTaskInfos(new TaskInfoFactory<QueueTaskInfo>() {
          @Override
          public QueueTaskInfo getTaskInfo(Task<?> task) {
            return new QueueTaskInfo(task);
          }
        });
    Collections.sort(taskInfos, new Comparator<QueueTaskInfo>() {
      @Override
      public int compare(QueueTaskInfo a, QueueTaskInfo b) {
        if (a.state != b.state) {
          return a.state.ordinal() - b.state.ordinal();
        }

        int cmp = Long.signum(a.delayMillis - b.delayMillis);
        if (cmp != 0) {
          return cmp;
        }

        return a.getTaskString(taskNameWidth)
            .compareTo(b.getTaskString(taskNameWidth));
      }
    });
    return taskInfos;
  }

  private static String id(final int id) {
    return IdGenerator.format(id);
  }

  private static String time(final long now, final long delay) {
    final Date when = new Date(now + delay);
    if (delay < 24 * 60 * 60 * 1000L) {
      return new SimpleDateFormat("HH:mm:ss.SSS").format(when);
    }
    return new SimpleDateFormat("MMM-dd HH:mm").format(when);
  }

  private static String format(final Task.State state) {
    switch (state) {
      case DONE:
        return "....... done";
      case CANCELLED:
        return "..... killed";
      case RUNNING:
        return "";
      case READY:
        return "waiting ....";
      case SLEEPING:
        return "sleeping";
      default:
        return state.toString();
    }
  }

  private static class QueueTaskInfo {
    private final long delayMillis;
    private final Task.State state;
    private final Task<?> task;

    QueueTaskInfo(Task<?> task) {
      this.task = task;
      this.delayMillis = task.getDelay(TimeUnit.MILLISECONDS);
      this.state = task.getState();
    }

    String getRemoteName() {
      if (task instanceof ProjectTask) {
        return ((ProjectTask<?>) task).getRemoteName();
      }
      return null;
    }

    Project.NameKey getProjectNameKey() {
      if (task instanceof ProjectTask<?>) {
        return ((ProjectTask<?>) task).getProjectNameKey();
      }
      return null;
    }

    boolean hasCustomizedPrint() {
      if (task instanceof ProjectTask<?>) {
        return ((ProjectTask<?>) task).hasCustomizedPrint();
      }
      return false;
    }

    int getTaskId() {
      return task.getTaskId();
    }

    String getTaskString(int maxLength) {
      String s = task.toString();
      return s.length() < maxLength ? s : s.substring(0, maxLength);
    }
  }
}
