// 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.google.gerrit.httpd.rpc.project;

import static com.google.gerrit.common.ProjectAccessUtil.mergeSections;

import com.google.common.base.Objects;
import com.google.gerrit.common.data.AccessSection;
import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.common.data.PermissionRule;
import com.google.gerrit.common.errors.InvalidNameException;
import com.google.gerrit.common.errors.NoSuchGroupException;
import com.google.gerrit.common.errors.UpdateParentFailedException;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.httpd.rpc.Handler;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.account.GroupBackend;
import com.google.gerrit.server.account.GroupBackends;
import com.google.gerrit.server.config.AllProjectsNameProvider;
import com.google.gerrit.server.git.MetaDataUpdate;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.gerrit.server.project.ProjectControl;
import com.google.gerrit.server.project.RefControl;
import com.google.gerrit.server.project.SetParent;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Provider;

import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.ObjectId;

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

public abstract class ProjectAccessHandler<T> extends Handler<T> {

  private final ProjectControl.Factory projectControlFactory;
  protected final GroupBackend groupBackend;
  private final MetaDataUpdate.User metaDataUpdateFactory;
  private final AllProjectsNameProvider allProjects;
  private final Provider<SetParent> setParent;

  protected final Project.NameKey projectName;
  protected final ObjectId base;
  private List<AccessSection> sectionList;
  private final Project.NameKey parentProjectName;
  protected String message;
  private boolean checkIfOwner;

  protected ProjectAccessHandler(ProjectControl.Factory projectControlFactory,
      GroupBackend groupBackend, MetaDataUpdate.User metaDataUpdateFactory,
      AllProjectsNameProvider allProjects, Provider<SetParent> setParent,
      Project.NameKey projectName, ObjectId base,
      List<AccessSection> sectionList, Project.NameKey parentProjectName,
      String message, boolean checkIfOwner) {
    this.projectControlFactory = projectControlFactory;
    this.groupBackend = groupBackend;
    this.metaDataUpdateFactory = metaDataUpdateFactory;
    this.allProjects = allProjects;
    this.setParent = setParent;

    this.projectName = projectName;
    this.base = base;
    this.sectionList = sectionList;
    this.parentProjectName = parentProjectName;
    this.message = message;
    this.checkIfOwner = checkIfOwner;
  }

  @Override
  public final T call() throws NoSuchProjectException, IOException,
      ConfigInvalidException, InvalidNameException, NoSuchGroupException,
      OrmException, UpdateParentFailedException {
    final ProjectControl projectControl =
        projectControlFactory.controlFor(projectName);

    final MetaDataUpdate md;
    try {
      md = metaDataUpdateFactory.create(projectName);
    } catch (RepositoryNotFoundException notFound) {
      throw new NoSuchProjectException(projectName);
    }
    try {
      ProjectConfig config = ProjectConfig.read(md, base);
      Set<String> toDelete = scanSectionNames(config);

      for (AccessSection section : mergeSections(sectionList)) {
        String name = section.getName();

        if (AccessSection.GLOBAL_CAPABILITIES.equals(name)) {
          if (checkIfOwner && !projectControl.isOwner()) {
            continue;
          }
          replace(config, toDelete, section);

        } else if (AccessSection.isValid(name)) {
          if (checkIfOwner && !projectControl.controlForRef(name).isOwner()) {
            continue;
          }

          RefControl.validateRefPattern(name);

          replace(config, toDelete, section);
        }
      }

      for (String name : toDelete) {
        if (AccessSection.GLOBAL_CAPABILITIES.equals(name)) {
          if (!checkIfOwner || projectControl.isOwner()) {
            config.remove(config.getAccessSection(name));
          }

        } else if (!checkIfOwner ||  projectControl.controlForRef(name).isOwner()) {
          config.remove(config.getAccessSection(name));
        }
      }

      boolean parentProjectUpdate = false;
      if (!config.getProject().getNameKey().equals(allProjects.get()) &&
          !config.getProject().getParent(allProjects.get()).equals(parentProjectName)) {
        parentProjectUpdate = true;
        try {
          setParent.get().validateParentUpdate(projectControl,
              Objects.firstNonNull(parentProjectName, allProjects.get()).get(),
              checkIfOwner);
        } catch (AuthException e) {
          throw new UpdateParentFailedException(
              "You are not allowed to change the parent project since you are "
              + "not an administrator. You may save the modifications for review "
              + "so that an administrator can approve them.", e);
        } catch (ResourceConflictException e) {
          throw new UpdateParentFailedException(e.getMessage(), e);
        } catch (UnprocessableEntityException e) {
          throw new UpdateParentFailedException(e.getMessage(), e);
        }
        config.getProject().setParentName(parentProjectName);
      }

      if (message != null && !message.isEmpty()) {
        if (!message.endsWith("\n")) {
          message += "\n";
        }
        md.setMessage(message);
      } else {
        md.setMessage("Modify access rules\n");
      }

      return updateProjectConfig(config, md, parentProjectUpdate);
    } finally {
      md.close();
    }
  }

  protected abstract T updateProjectConfig(ProjectConfig config,
      MetaDataUpdate md, boolean parentProjectUpdate) throws IOException,
      NoSuchProjectException, ConfigInvalidException, OrmException;

  private void replace(ProjectConfig config, Set<String> toDelete,
      AccessSection section) throws NoSuchGroupException {
    for (Permission permission : section.getPermissions()) {
      for (PermissionRule rule : permission.getRules()) {
        lookupGroup(rule);
      }
    }
    config.replace(section);
    toDelete.remove(section.getName());
  }

  private static Set<String> scanSectionNames(ProjectConfig config) {
    Set<String> names = new HashSet<String>();
    for (AccessSection section : config.getAccessSections()) {
      names.add(section.getName());
    }
    return names;
  }

  private void lookupGroup(PermissionRule rule) throws NoSuchGroupException {
    GroupReference ref = rule.getGroup();
    if (ref.getUUID() == null) {
      final GroupReference group =
          GroupBackends.findBestSuggestion(groupBackend, ref.getName());
      if (group == null) {
        throw new NoSuchGroupException(ref.getName());
      }
      ref.setUUID(group.getUUID());
    }
  }
}
