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

import com.google.common.base.Objects;
import com.google.gerrit.common.ProjectUtil;
import com.google.gerrit.common.data.AccessSection;
import com.google.gerrit.common.data.GroupDescription;
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.ProjectCreationFailedException;
import com.google.gerrit.extensions.events.NewProjectCreatedListener;
import com.google.gerrit.extensions.registration.DynamicSet;
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.reviewdb.client.Project.SubmitType;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.GroupBackend;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.ProjectOwnerGroups;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.MetaDataUpdate;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.git.RepositoryCaseMismatchException;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;

import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.lib.Repository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;


/** Common class that holds the code to create projects */
public class PerformCreateProject {
  private static final Logger log = LoggerFactory
      .getLogger(PerformCreateProject.class);

  public interface Factory {
    PerformCreateProject create(CreateProjectArgs createProjectArgs);
  }

  private final Config cfg;
  private final Set<AccountGroup.UUID> projectOwnerGroups;
  private final IdentifiedUser currentUser;
  private final GitRepositoryManager repoManager;
  private final GitReferenceUpdated referenceUpdated;
  private final DynamicSet<NewProjectCreatedListener> createdListener;
  private final PersonIdent serverIdent;
  private final CreateProjectArgs createProjectArgs;
  private final ProjectCache projectCache;
  private final GroupBackend groupBackend;
  private final MetaDataUpdate.User metaDataUpdateFactory;

  @Inject
  PerformCreateProject(@GerritServerConfig Config cfg,
      @ProjectOwnerGroups Set<AccountGroup.UUID> pOwnerGroups,
      IdentifiedUser identifiedUser, GitRepositoryManager gitRepoManager,
      GitReferenceUpdated referenceUpdated,
      DynamicSet<NewProjectCreatedListener> createdListener,
      @GerritPersonIdent PersonIdent personIdent, GroupBackend groupBackend,
      MetaDataUpdate.User metaDataUpdateFactory,
      @Assisted CreateProjectArgs createPArgs, ProjectCache pCache) {
    this.cfg = cfg;
    this.projectOwnerGroups = pOwnerGroups;
    this.currentUser = identifiedUser;
    this.repoManager = gitRepoManager;
    this.referenceUpdated = referenceUpdated;
    this.createdListener = createdListener;
    this.serverIdent = personIdent;
    this.createProjectArgs = createPArgs;
    this.projectCache = pCache;
    this.groupBackend = groupBackend;
    this.metaDataUpdateFactory = metaDataUpdateFactory;
  }

  public Project createProject() throws ProjectCreationFailedException {
    validateParameters();
    final Project.NameKey nameKey = createProjectArgs.getProject();
    try {
      final String head =
          createProjectArgs.permissionsOnly ? RefNames.REFS_CONFIG
              : createProjectArgs.branch.get(0);
      final Repository repo = repoManager.createRepository(nameKey);
      try {
        NewProjectCreatedListener.Event event = new NewProjectCreatedListener.Event() {
          @Override
          public String getProjectName() {
            return nameKey.get();
          }

          @Override
          public String getHeadName() {
            return head;
          }
        };
        for (NewProjectCreatedListener l : createdListener) {
          try {
            l.onNewProjectCreated(event);
          } catch (RuntimeException e) {
            log.warn("Failure in NewProjectCreatedListener", e);
          }
        }

        final RefUpdate u = repo.updateRef(Constants.HEAD);
        u.disableRefLog();
        u.link(head);

        createProjectConfig();

        if (!createProjectArgs.permissionsOnly
            && createProjectArgs.createEmptyCommit) {
          createEmptyCommits(repo, nameKey, createProjectArgs.branch);
        }

        return projectCache.get(nameKey).getProject();
      } finally {
        repo.close();
      }
    } catch (RepositoryCaseMismatchException e) {
      throw new ProjectCreationFailedException("Cannot create " + nameKey.get()
          + " because the name is already occupied by another project."
          + " The other project has the same name, only spelled in a"
          + " different case.", e);
    } catch (RepositoryNotFoundException badName) {
      throw new ProjectCreationFailedException("Cannot create " + nameKey, badName);
    } catch (IllegalStateException err) {
      try {
        final Repository repo = repoManager.openRepository(nameKey);
        try {
          if (repo.getObjectDatabase().exists()) {
            throw new ProjectCreationFailedException("project \"" + nameKey + "\" exists");
          }
          throw err;
        } finally {
          repo.close();
        }
      } catch (IOException ioErr) {
        final String msg = "Cannot create " + nameKey;
        log.error(msg, err);
        throw new ProjectCreationFailedException(msg, ioErr);
      }
    } catch (Exception e) {
      final String msg = "Cannot create " + nameKey;
      log.error(msg, e);
      throw new ProjectCreationFailedException(msg, e);
    }
  }

  private void createProjectConfig() throws IOException, ConfigInvalidException {
    final MetaDataUpdate md =
        metaDataUpdateFactory.create(createProjectArgs.getProject());
    try {
      final ProjectConfig config = ProjectConfig.read(md);
      config.load(md);

      Project newProject = config.getProject();
      newProject.setDescription(createProjectArgs.projectDescription);
      newProject.setSubmitType(Objects.firstNonNull(createProjectArgs.submitType,
          cfg.getEnum("repository", "*", "defaultSubmitType", SubmitType.MERGE_IF_NECESSARY)));
      newProject
          .setUseContributorAgreements(createProjectArgs.contributorAgreements);
      newProject.setUseSignedOffBy(createProjectArgs.signedOffBy);
      newProject.setUseContentMerge(createProjectArgs.contentMerge);
      newProject.setRequireChangeID(createProjectArgs.changeIdRequired);
      newProject.setMaxObjectSizeLimit(createProjectArgs.maxObjectSizeLimit);
      if (createProjectArgs.newParent != null) {
        newProject.setParentName(createProjectArgs.newParent.getProject()
            .getNameKey());
      }

      if (!createProjectArgs.ownerIds.isEmpty()) {
        final AccessSection all =
            config.getAccessSection(AccessSection.ALL, true);
        for (AccountGroup.UUID ownerId : createProjectArgs.ownerIds) {
          GroupDescription.Basic g = groupBackend.get(ownerId);
          if (g != null) {
            GroupReference group = config.resolve(GroupReference.forGroup(g));
            all.getPermission(Permission.OWNER, true).add(
                new PermissionRule(group));
          }
        }
      }

      md.setMessage("Created project\n");
      config.commit(md);
    } finally {
      md.close();
    }
    projectCache.onCreateProject(createProjectArgs.getProject());
    repoManager.setProjectDescription(createProjectArgs.getProject(),
        createProjectArgs.projectDescription);
  }

  private void validateParameters() throws ProjectCreationFailedException {
    if (createProjectArgs.getProjectName() == null
        || createProjectArgs.getProjectName().isEmpty()) {
      throw new ProjectCreationFailedException("Project name is required");
    }

    String nameWithoutSuffix = ProjectUtil.stripGitSuffix(createProjectArgs.getProjectName());
    createProjectArgs.setProjectName(nameWithoutSuffix);

    if (!currentUser.getCapabilities().canCreateProject()) {
      throw new ProjectCreationFailedException(String.format(
          "%s does not have \"Create Project\" capability.",
          currentUser.getUserName()));
    }

    if (createProjectArgs.ownerIds == null
        || createProjectArgs.ownerIds.isEmpty()) {
      createProjectArgs.ownerIds =
          new ArrayList<AccountGroup.UUID>(projectOwnerGroups);
    }

    List<String> transformedBranches = new ArrayList<String>();
    if (createProjectArgs.branch == null ||
        createProjectArgs.branch.isEmpty()) {
      createProjectArgs.branch = Collections.singletonList(Constants.MASTER);
    }
    for (String branch : createProjectArgs.branch) {
      while (branch.startsWith("/")) {
        branch = branch.substring(1);
      }
      if (!branch.startsWith(Constants.R_HEADS)) {
        branch = Constants.R_HEADS + branch;
      }
      if (!Repository.isValidRefName(branch)) {
        throw new ProjectCreationFailedException(String.format(
            "Branch \"%s\" is not a valid name.", branch));
      }
      if (!transformedBranches.contains(branch)) {
        transformedBranches.add(branch);
      }
    }
    createProjectArgs.branch = transformedBranches;
  }

  private void createEmptyCommits(final Repository repo,
      final Project.NameKey project, final List<String> refs)
      throws IOException {
    ObjectInserter oi = repo.newObjectInserter();
    try {
      CommitBuilder cb = new CommitBuilder();
      cb.setTreeId(oi.insert(Constants.OBJ_TREE, new byte[] {}));
      cb.setAuthor(metaDataUpdateFactory.getUserPersonIdent());
      cb.setCommitter(serverIdent);
      cb.setMessage("Initial empty repository\n");

      ObjectId id = oi.insert(cb);
      oi.flush();

      for (String ref : refs) {
        RefUpdate ru = repo.updateRef(ref);
        ru.setNewObjectId(id);
        final Result result = ru.update();
        switch (result) {
          case NEW:
            referenceUpdated.fire(project, ru);
            break;
          default: {
            throw new IOException(String.format(
              "Failed to create ref \"%s\": %s", ref, result.name()));
          }
        }
      }
    } catch (IOException e) {
      log.error(
          "Cannot create empty commit for "
              + createProjectArgs.getProjectName(), e);
      throw e;
    } finally {
      oi.release();
    }
  }
}
