// 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.Account.Id;
import com.google.gerrit.reviewdb.server.ReviewDb;
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.GetGroups;
import com.google.gerrit.server.git.MetaDataUpdate;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.sshd.CommandMetaData;
import com.google.gerrit.sshd.SshCommand;
import com.google.gwtorm.server.SchemaFactory;
import com.google.inject.Inject;
import com.google.inject.Provider;

import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

@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,
      SchemaFactory<ReviewDb> schema) {
    this.metaDataUpdateFactory = metaDataUpdateFactory;
    this.accountGetGroups = accountGetGroups;
    this.accountResolver = accountResolver;
    this.userFactory = userFactory;
    this.schema = schema;
  }

  private final MetaDataUpdate.Server metaDataUpdateFactory;
  private final AccountResolver accountResolver;
  private final Provider<GetGroups> accountGetGroups;
  private final IdentifiedUser.GenericFactory userFactory;
  private final SchemaFactory<ReviewDb> schema;
  private int columns = 80;
  private int permissionGroupWidth;

  @Override
  public void run() throws UnloggedFailure, Failure, Exception {
    Account 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\"");
    }
    try (ReviewDb db = schema.open()) {
      Set<Id> idList = accountResolver.findAll(db, name);
      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 = new Project.NameKey(projectName);

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

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

        for (Id id : idList) {
          userHasPermissionsInProject = false;
          account = accountResolver.find(db, id.toString());
          stdout.println("Full name:         " + account.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().equals(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);
  }
}
