// 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.AccessSection;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.common.data.PermissionRule;
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.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Project;
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.AccountState;
import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.gerrit.server.project.ProjectConfig;
import com.google.gerrit.server.restapi.account.GetGroups;
import com.google.gerrit.sshd.CommandMetaData;
import com.google.gerrit.sshd.SshCommand;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option;

@RequiresCapability(value = GlobalCapability.ADMINISTRATE_SERVER, scope = CapabilityScope.CORE)
@CommandMetaData(
    name = "show-repo-account-access",
    description = "Displays user's access on a specific repository")
public final class ShowRepoAccountAccessCommand extends SshCommand {

  @Argument(usage = "project to show access for?")
  private String projectName = "";

  @Option(
      name = "--user",
      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-repo-account-access All-Projects --user Last,\\\\ First\"")
  private String name = "";

  @Option(name = "-w", usage = "display without line width truncation")
  private boolean wide;

  @Inject
  ShowRepoAccountAccessCommand(
      MetaDataUpdate.Server metaDataUpdateFactory,
      Provider<GetGroups> accountGetGroups,
      AccountResolver accountResolver,
      IdentifiedUser.GenericFactory userFactory,
      ProjectConfig.Factory projectConfigFactory) {
    this.metaDataUpdateFactory = metaDataUpdateFactory;
    this.accountGetGroups = accountGetGroups;
    this.accountResolver = accountResolver;
    this.userFactory = userFactory;
    this.projectConfigFactory = projectConfigFactory;
  }

  private final MetaDataUpdate.Server metaDataUpdateFactory;
  private final AccountResolver accountResolver;
  private final Provider<GetGroups> accountGetGroups;
  private final IdentifiedUser.GenericFactory userFactory;
  private final ProjectConfig.Factory projectConfigFactory;
  private int columns = 80;
  private int permissionGroupWidth;

  @Override
  public void run() throws UnloggedFailure, Failure, Exception {
    AccountState account;
    String sectionNameFormatter = "  %-25s\n";
    String ruleNameFormatter = "    %-15s\n ";
    String permissionNameFormatter = "      %5s %9s %s\n";

    Boolean userHasPermissionsInSection = false;
    Boolean userHasPermissionsInProject = false;

    if (projectName.isEmpty()) {
      throw new UnloggedFailure(1, "Please specify a project to show access for");
    }

    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-repo-account-access All-Projects --user Last,\\\\ First\"");
    }
    Set<Account.Id> idList = accountResolver.resolve(name).asIdSet();
    if (idList.isEmpty()) {
      throw new UnloggedFailure(
          1,
          "No accounts found for your query: \""
              + name
              + "\""
              + " Tip: Try double-escaping spaces, for example: \"--user Last,\\\\ First\"");
    }

    Project.NameKey nameKey = Project.nameKey(projectName);

    try {
      MetaDataUpdate md = metaDataUpdateFactory.create(nameKey);
      ProjectConfig config;
      config = projectConfigFactory.read(md);

      permissionGroupWidth = wide ? Integer.MAX_VALUE : columns - 9 - 5 - 9;

      for (Account.Id id : idList) {
        userHasPermissionsInProject = false;
        account = accountResolver.resolve(id.toString()).asUnique();
        stdout.println("Full name:         " + account.getAccount().getFullName());
        // Need to know what groups the user is in. This is not a great
        // solution, but it does work.
        List<GroupInfo> groupInfos =
            accountGetGroups.get().apply(new AccountResource(userFactory.create(id)));
        HashSet<String> groupHash = new HashSet<>();

        for (GroupInfo groupInfo : groupInfos) {
          groupHash.add(groupInfo.name);
        }

        for (AccessSection accessSection : config.getAccessSections()) {
          StringBuilder sb = new StringBuilder();
          sb.append((String.format(sectionNameFormatter, accessSection.getName().toString())));
          // This is a solution to prevent displaying a section heading unless
          // the user has permissions for it
          // not the best solution, but I haven't been able to find
          // "Is user a member of this group" based on the information I have
          // in a more efficient manner yet.
          userHasPermissionsInSection = false;
          for (Permission permission : accessSection.getPermissions()) {

            for (PermissionRule rule : permission.getRules()) {

              if (groupHash.contains(rule.getGroup().getName())) {
                sb.append(String.format(ruleNameFormatter, permission.getName()));
                sb.append(
                    String.format(
                        permissionNameFormatter,
                        (rule.getMin() != rule.getMax())
                            ? "" + rule.getMin() + " " + rule.getMax()
                            : rule.getAction(),
                        (permission.getExclusiveGroup() ? "EXCLUSIVE" : ""),
                        format(rule.getGroup().getName())));
                userHasPermissionsInSection = true;
              }
            }
          }

          if (userHasPermissionsInSection) {
            stdout.print(sb.toString());

            userHasPermissionsInProject = true;
          }
        }

        if (!userHasPermissionsInProject) {
          stdout.println("  No access found for this user on this repository");
        }
      }
    } catch (RepositoryNotFoundException e) {
      throw new UnloggedFailure(1, "Repository not found");
    }
  }

  private String format(String s) {
    if (s.length() < permissionGroupWidth) {
      return s;
    }
    return s.substring(0, permissionGroupWidth);
  }
}
