// Copyright (C) 2012 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.googlesource.gerrit.plugins.adminconsole;

import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.extensions.annotations.CapabilityScope;
import com.google.gerrit.extensions.annotations.RequiresCapability;
import com.google.gerrit.extensions.common.GroupInfo;
import com.google.gerrit.extensions.common.SshKeyInfo;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Account.Id;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountResolver;
import com.google.gerrit.server.account.AccountResource;
import com.google.gerrit.server.account.GetGroups;
import com.google.gerrit.server.account.GetSshKeys;
import com.google.gerrit.server.account.externalids.ExternalId;
import com.google.gerrit.server.account.externalids.ExternalIds;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.sshd.CommandMetaData;
import com.google.gerrit.sshd.SshCommand;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.io.IOException;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option;

@RequiresCapability(value = GlobalCapability.ADMINISTRATE_SERVER, scope = CapabilityScope.CORE)
@CommandMetaData(name = "show-account", description = "Displays user information")
public final class ShowAccountCommand extends SshCommand {

  @Argument(
    usage =
        "User information to find: LastName,\\ Firstname,  email@address.com, account id or an user name.  Be sure to double-escape spaces, for example: \"show-account Last,\\\\ First\""
  )
  private String name = "";

  @Option(name = "--show-groups", usage = "show group membership by user?")
  private boolean showGroups = false;

  @Option(name = "--filter-groups", usage = "filter group string")
  private String filterGroups = null;

  @Option(name = "--show-keys", usage = "show user's public keys?")
  private boolean showKeys = false;

  private final AccountResolver accountResolver;
  private final Provider<GetGroups> accountGetGroups;
  private final IdentifiedUser.GenericFactory userFactory;
  private final Provider<GetSshKeys> getSshKeys;
  private final ExternalIds externalIds;

  @Inject
  ShowAccountCommand(
      AccountResolver accountResolver,
      Provider<GetGroups> accountGetGroups,
      IdentifiedUser.GenericFactory userFactory,
      Provider<GetSshKeys> getSshKeys,
      ExternalIds externalIds) {
    this.accountResolver = accountResolver;
    this.accountGetGroups = accountGetGroups;
    this.userFactory = userFactory;
    this.getSshKeys = getSshKeys;
    this.externalIds = externalIds;
  }

  @Override
  public void run() throws UnloggedFailure, Exception {
    Account account;

    if (name.isEmpty()) {
      throw new UnloggedFailure(
          1,
          "You need to tell me who to find:  LastName,\\\\ Firstname, email@address.com, account id or an user name.  "
              + "Be sure to double-escape spaces, for example: \"show-account Last,\\\\ First\"");
    }
    Set<Id> idList = accountResolver.findAll(name);
    if (idList.isEmpty()) {
      throw new UnloggedFailure(
          1,
          "No accounts found for your query: \""
              + name
              + "\""
              + " Tip: Try double-escaping spaces, for example: \"show-account Last,\\\\ First\"");
    }
    stdout.println(
        "Found "
            + idList.size()
            + " result"
            + (idList.size() > 1 ? "s" : "")
            + ": for query: \""
            + name
            + "\"");
    stdout.println();

    for (Id id : idList) {
      account = accountResolver.find(id.toString());
      if (account == null) {
        throw new UnloggedFailure("Account " + id.toString() + " does not exist.");
      }
      stdout.println("Full name:         " + account.getFullName());
      stdout.println("Account Id:        " + id.toString());
      stdout.println("Preferred Email:   " + account.getPreferredEmail());
      stdout.println("User Name:         " + account.getUserName());
      stdout.println("Active:            " + account.isActive());
      stdout.println("Registered on:     " + account.getRegisteredOn());

      stdout.println("");
      stdout.println("External Ids:");
      stdout.println(String.format("%-50s %s", "Email Address:", "External Id:"));
      try {
        for (ExternalId externalId : externalIds.byAccount(account.getId())) {
          stdout.println(
              String.format(
                  "%-50s %s",
                  (externalId.email() == null ? "" : externalId.email()), externalId.key()));
        }
      } catch (IOException e) {
        throw new UnloggedFailure(1, "Error getting external Ids: " + e.getMessage(), e);
      }
      if (showKeys) {
        stdout.println("");
        stdout.println("Public Keys:");
        List<SshKeyInfo> sshKeys;
        try {
          sshKeys = getSshKeys.get().apply(new AccountResource(userFactory.create(id)));
        } catch (AuthException
            | IOException
            | ConfigInvalidException
            | PermissionBackendException e) {
          throw new UnloggedFailure(1, "Error getting sshkeys: " + e.getMessage(), e);
        }
        if (sshKeys == null || sshKeys.isEmpty()) {
          stdout.println("None");
        } else {
          stdout.println(String.format("%-9s %s", "Status:", "Key:"));
          for (SshKeyInfo sshKey : sshKeys) {
            stdout.println(
                String.format(
                    "%-9s %s", (sshKey.valid ? "Active" : "Inactive"), sshKey.sshPublicKey));
          }
        }
      }

      if (showGroups) {
        stdout.println();
        stdout.println(
            "Member of groups"
                + (filterGroups == null ? "" : " (Filtering on \"" + filterGroups + "\")")
                + ":");
        List<GroupInfo> groupInfos =
            accountGetGroups.get().apply(new AccountResource(userFactory.create(id)));

        Collections.sort(groupInfos, new CustomComparator());
        for (GroupInfo groupInfo : groupInfos) {
          if (null == filterGroups
              || groupInfo.name.toLowerCase().contains(filterGroups.toLowerCase())) {
            stdout.println(groupInfo.name);
          }
        }
      }
      stdout.println("");
    }
  }

  private static class CustomComparator implements Comparator<GroupInfo> {
    @Override
    public int compare(GroupInfo o1, GroupInfo o2) {
      return o1.name.compareTo(o2.name);
    }
  }
}
