// Copyright (C) 2016 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.server.restapi.project;

import static com.google.gerrit.server.permissions.GlobalPermission.ADMINISTRATE_SERVER;
import static com.google.gerrit.server.permissions.ProjectPermission.CREATE_REF;
import static com.google.gerrit.server.permissions.ProjectPermission.CREATE_TAG_REF;
import static com.google.gerrit.server.permissions.RefPermission.CREATE_CHANGE;
import static com.google.gerrit.server.permissions.RefPermission.READ;
import static com.google.gerrit.server.permissions.RefPermission.WRITE_CONFIG;
import static java.util.stream.Collectors.toMap;

import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.Iterables;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.data.AccessSection;
import com.google.gerrit.common.data.GroupDescription;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.common.data.PermissionRule;
import com.google.gerrit.common.data.RefConfigSection;
import com.google.gerrit.common.data.WebLinkInfoCommon;
import com.google.gerrit.extensions.api.access.AccessSectionInfo;
import com.google.gerrit.extensions.api.access.PermissionInfo;
import com.google.gerrit.extensions.api.access.PermissionRuleInfo;
import com.google.gerrit.extensions.api.access.ProjectAccessInfo;
import com.google.gerrit.extensions.common.GroupInfo;
import com.google.gerrit.extensions.common.WebLinkInfo;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.WebLinks;
import com.google.gerrit.server.account.GroupBackend;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.gerrit.server.permissions.GlobalPermission;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.permissions.ProjectPermission;
import com.google.gerrit.server.permissions.RefPermission;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectConfig;
import com.google.gerrit.server.project.ProjectJson;
import com.google.gerrit.server.project.ProjectResource;
import com.google.gerrit.server.project.ProjectState;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;

@Singleton
public class GetAccess implements RestReadView<ProjectResource> {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  public static final ImmutableBiMap<PermissionRule.Action, PermissionRuleInfo.Action> ACTION_TYPE =
      ImmutableBiMap.of(
          PermissionRule.Action.ALLOW,
          PermissionRuleInfo.Action.ALLOW,
          PermissionRule.Action.BATCH,
          PermissionRuleInfo.Action.BATCH,
          PermissionRule.Action.BLOCK,
          PermissionRuleInfo.Action.BLOCK,
          PermissionRule.Action.DENY,
          PermissionRuleInfo.Action.DENY,
          PermissionRule.Action.INTERACTIVE,
          PermissionRuleInfo.Action.INTERACTIVE);

  private final Provider<CurrentUser> user;
  private final PermissionBackend permissionBackend;
  private final AllProjectsName allProjectsName;
  private final ProjectJson projectJson;
  private final ProjectCache projectCache;
  private final Provider<MetaDataUpdate.Server> metaDataUpdateFactory;
  private final GroupBackend groupBackend;
  private final WebLinks webLinks;

  @Inject
  public GetAccess(
      Provider<CurrentUser> self,
      PermissionBackend permissionBackend,
      AllProjectsName allProjectsName,
      ProjectCache projectCache,
      Provider<MetaDataUpdate.Server> metaDataUpdateFactory,
      ProjectJson projectJson,
      GroupBackend groupBackend,
      WebLinks webLinks) {
    this.user = self;
    this.permissionBackend = permissionBackend;
    this.allProjectsName = allProjectsName;
    this.projectJson = projectJson;
    this.projectCache = projectCache;
    this.metaDataUpdateFactory = metaDataUpdateFactory;
    this.groupBackend = groupBackend;
    this.webLinks = webLinks;
  }

  public ProjectAccessInfo apply(Project.NameKey nameKey)
      throws ResourceNotFoundException, ResourceConflictException, IOException,
          PermissionBackendException {
    ProjectState state = projectCache.checkedGet(nameKey);
    if (state == null) {
      throw new ResourceNotFoundException(nameKey.get());
    }
    return apply(new ProjectResource(state, user.get()));
  }

  @Override
  public ProjectAccessInfo apply(ProjectResource rsrc)
      throws ResourceNotFoundException, ResourceConflictException, IOException,
          PermissionBackendException {
    // Load the current configuration from the repository, ensuring it's the most
    // recent version available. If it differs from what was in the project
    // state, force a cache flush now.

    Project.NameKey projectName = rsrc.getNameKey();
    ProjectAccessInfo info = new ProjectAccessInfo();
    ProjectState projectState = projectCache.checkedGet(projectName);
    PermissionBackend.ForProject perm = permissionBackend.currentUser().project(projectName);

    ProjectConfig config;
    try (MetaDataUpdate md = metaDataUpdateFactory.get().create(projectName)) {
      config = ProjectConfig.read(md);
      info.configWebLinks = new ArrayList<>();

      // config may have a null revision if the repo doesn't have its own refs/meta/config.
      if (config.getRevision() != null) {
        // WebLinks operates in terms of the data types used in the GWT UI. Once the GWT UI is
        // gone, WebLinks should be fixed to use the extension data types.
        for (WebLinkInfoCommon wl :
            webLinks.getFileHistoryLinks(
                projectName.get(), config.getRevision().getName(), ProjectConfig.PROJECT_CONFIG)) {
          info.configWebLinks.add(new WebLinkInfo(wl.name, wl.imageUrl, wl.url, wl.target));
        }
      }

      if (config.updateGroupNames(groupBackend)) {
        md.setMessage("Update group names\n");
        config.commit(md);
        projectCache.evict(config.getProject());
        projectState = projectCache.checkedGet(projectName);
        perm = permissionBackend.currentUser().project(projectName);
      } else if (config.getRevision() != null
          && !config.getRevision().equals(projectState.getConfig().getRevision())) {
        projectCache.evict(config.getProject());
        projectState = projectCache.checkedGet(projectName);
        perm = permissionBackend.currentUser().project(projectName);
      }
    } catch (ConfigInvalidException e) {
      throw new ResourceConflictException(e.getMessage());
    } catch (RepositoryNotFoundException e) {
      throw new ResourceNotFoundException(rsrc.getName(), e);
    }

    // The following implementation must match the ProjectAccessFactory JSON RPC endpoint.

    info.local = new HashMap<>();
    info.ownerOf = new HashSet<>();
    Map<AccountGroup.UUID, GroupInfo> groups = new HashMap<>();
    boolean canReadConfig = check(perm, RefNames.REFS_CONFIG, READ);
    boolean canWriteConfig = check(perm, ProjectPermission.WRITE_CONFIG);

    // Check if the project state permits read only when the user is not allowed to write the config
    // (=owner). This is so that the owner can still read (and in the next step write) the project's
    // config to set the project state to any state that is not HIDDEN.
    if (!canWriteConfig) {
      projectState.checkStatePermitsRead();
    }

    for (AccessSection section : config.getAccessSections()) {
      String name = section.getName();
      if (AccessSection.GLOBAL_CAPABILITIES.equals(name)) {
        if (canWriteConfig) {
          info.local.put(name, createAccessSection(groups, section));
          info.ownerOf.add(name);

        } else if (canReadConfig) {
          info.local.put(section.getName(), createAccessSection(groups, section));
        }

      } else if (RefConfigSection.isValid(name)) {
        if (check(perm, name, WRITE_CONFIG)) {
          info.local.put(name, createAccessSection(groups, section));
          info.ownerOf.add(name);

        } else if (canReadConfig) {
          info.local.put(name, createAccessSection(groups, section));

        } else if (check(perm, name, READ)) {
          // Filter the section to only add rules describing groups that
          // are visible to the current-user. This includes any group the
          // user is a member of, as well as groups they own or that
          // are visible to all users.

          AccessSection dst = null;
          for (Permission srcPerm : section.getPermissions()) {
            Permission dstPerm = null;

            for (PermissionRule srcRule : srcPerm.getRules()) {
              AccountGroup.UUID groupId = srcRule.getGroup().getUUID();
              if (groupId == null) {
                continue;
              }

              loadGroup(groups, groupId);
              if (dstPerm == null) {
                if (dst == null) {
                  dst = new AccessSection(name);
                  info.local.put(name, createAccessSection(groups, dst));
                }
                dstPerm = dst.getPermission(srcPerm.getName(), true);
              }
              dstPerm.add(srcRule);
            }
          }
        }
      }
    }

    if (info.ownerOf.isEmpty()) {
      try {
        permissionBackend.currentUser().check(GlobalPermission.ADMINISTRATE_SERVER);
        // Special case: If the section list is empty, this project has no current
        // access control information. Fall back to site administrators.
        info.ownerOf.add(AccessSection.ALL);
      } catch (AuthException e) {
        // Do nothing.
      }
    }

    if (config.getRevision() != null) {
      info.revision = config.getRevision().name();
    }

    ProjectState parent = Iterables.getFirst(projectState.parents(), null);
    if (parent != null) {
      info.inheritsFrom = projectJson.format(parent.getProject());
    }

    if (projectName.equals(allProjectsName)
        && permissionBackend.currentUser().testOrFalse(ADMINISTRATE_SERVER)) {
      info.ownerOf.add(AccessSection.GLOBAL_CAPABILITIES);
    }

    info.isOwner = toBoolean(canWriteConfig);
    info.canUpload =
        toBoolean(
            projectState.statePermitsWrite()
                && (canWriteConfig
                    || (canReadConfig
                        && perm.ref(RefNames.REFS_CONFIG).testOrFalse(CREATE_CHANGE))));
    info.canAdd = toBoolean(perm.testOrFalse(CREATE_REF));
    info.canAddTags = toBoolean(perm.testOrFalse(CREATE_TAG_REF));
    info.configVisible = canReadConfig || canWriteConfig;

    info.groups =
        groups.entrySet().stream()
            .filter(e -> e.getValue() != null)
            .collect(toMap(e -> e.getKey().get(), Map.Entry::getValue));

    return info;
  }

  private void loadGroup(Map<AccountGroup.UUID, GroupInfo> groups, AccountGroup.UUID id) {
    if (!groups.containsKey(id)) {
      GroupDescription.Basic basic = groupBackend.get(id);
      GroupInfo group;
      if (basic != null) {
        group = new GroupInfo();
        // The UI only needs name + URL, so don't populate other fields to avoid leaking data
        // about groups invisible to the user.
        group.name = basic.getName();
        group.url = basic.getUrl();
      } else {
        logger.atWarning().log("no such group: %s", id);
        group = null;
      }
      groups.put(id, group);
    }
  }

  private static boolean check(PermissionBackend.ForProject ctx, String ref, RefPermission perm)
      throws PermissionBackendException {
    try {
      ctx.ref(ref).check(perm);
      return true;
    } catch (AuthException denied) {
      return false;
    }
  }

  private static boolean check(PermissionBackend.ForProject ctx, ProjectPermission perm)
      throws PermissionBackendException {
    try {
      ctx.check(perm);
      return true;
    } catch (AuthException denied) {
      return false;
    }
  }

  private AccessSectionInfo createAccessSection(
      Map<AccountGroup.UUID, GroupInfo> groups, AccessSection section) {
    AccessSectionInfo accessSectionInfo = new AccessSectionInfo();
    accessSectionInfo.permissions = new HashMap<>();
    for (Permission p : section.getPermissions()) {
      PermissionInfo pInfo = new PermissionInfo(p.getLabel(), p.getExclusiveGroup() ? true : null);
      pInfo.rules = new HashMap<>();
      for (PermissionRule r : p.getRules()) {
        PermissionRuleInfo info =
            new PermissionRuleInfo(ACTION_TYPE.get(r.getAction()), r.getForce());
        if (r.hasRange()) {
          info.max = r.getMax();
          info.min = r.getMin();
        }
        AccountGroup.UUID group = r.getGroup().getUUID();
        if (group != null) {
          pInfo.rules.putIfAbsent(group.get(), info); // First entry for the group wins
          loadGroup(groups, group);
        }
      }
      accessSectionInfo.permissions.put(p.getName(), pInfo);
    }
    return accessSectionInfo;
  }

  private static Boolean toBoolean(boolean value) {
    return value ? true : null;
  }
}
