// 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.ericsson.gerrit.plugins.projectgroupstructure;

import com.google.common.base.Charsets;
import com.google.common.hash.Hashing;
import com.google.gerrit.extensions.annotations.PluginCanonicalWebUrl;
import com.google.gerrit.extensions.api.groups.GroupInput;
import com.google.gerrit.extensions.common.GroupInfo;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.TopLevelResource;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.config.AllProjectsNameProvider;
import com.google.gerrit.server.group.CreateGroup;
import com.google.gerrit.server.project.CreateProjectArgs;
import com.google.gerrit.server.project.ProjectControl;
import com.google.gerrit.server.validators.ProjectCreationValidationListener;
import com.google.gerrit.server.validators.ValidationException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

@Singleton
public class ProjectCreationValidator
    implements ProjectCreationValidationListener {
  private static final Logger log =
      LoggerFactory.getLogger(ProjectCreationValidator.class);

  private static final String AN_ERROR_OCCURRED_MSG =
      "An error occurred while creating project, please contact Gerrit support";

  private static final String SEE_DOCUMENTATION_MSG =
      "\n\nSee documentation for more info: %s";

  private static final String MUST_BE_OWNER_TO_CREATE_PROJECT_MSG =
      "You must be owner of the parent project \"%s\" to create a nested project."
          + SEE_DOCUMENTATION_MSG;

  private static final String ROOT_PROJECT_CANNOT_CONTAINS_SLASHES_MSG =
      "Root project name cannot contains slashes." + SEE_DOCUMENTATION_MSG;

  private static final String REGULAR_PROJECT_NOT_ALLOWED_AS_ROOT_MSG =
      "Regular projects are not allowed as root.\n\n"
          + "Please create a root parent project (project with option "
          + "\"Only serve as parent for other projects\") that will hold "
          + "all your access rights and then create your regular project that "
          + "inherits rights from your root project.\n\n" + "Example:\n"
          + "\"someOrganization\"->parent project\n"
          + "\"someOrganization/someProject\"->regular project."
          + SEE_DOCUMENTATION_MSG;

  private static final String PROJECT_MUST_START_WITH_PARENT_NAME_MSG =
      "Project name must start with parent project name, e.g. %s."
          + SEE_DOCUMENTATION_MSG;

  private final CreateGroup.Factory createGroupFactory;
  private final String documentationUrl;
  private final AllProjectsNameProvider allProjectsName;

  @Inject
  public ProjectCreationValidator(CreateGroup.Factory createGroupFactory,
      @PluginCanonicalWebUrl String url,
      AllProjectsNameProvider allProjectsName) {
    this.createGroupFactory = createGroupFactory;
    this.documentationUrl = url + "Documentation/index.html";
    this.allProjectsName = allProjectsName;

  }

  @Override
  public void validateNewProject(CreateProjectArgs args)
      throws ValidationException {
    String name = args.getProjectName();
    log.debug("validating creation of {}", name);
    ProjectControl parentCtrl = args.newParent;
    if (parentCtrl.getUser().getCapabilities().canAdministrateServer()) {
      // Admins can bypass any rules to support creating projects that doesn't
      // comply with the new naming rules. New projects structures have to
      // comply but we need to be able to add new project to an existing non
      // compliant structure.
      log.debug("admin is creating project, bypassing all rules");
      return;
    }

    if (allProjectsName.get().equals(parentCtrl.getProject().getNameKey())) {
      validateRootProject(name, args.permissionsOnly);
      args.ownerIds.add(createGroup(name + "-admins"));
      return;
    }

    validateProject(name, parentCtrl);
  }

  private AccountGroup.UUID createGroup(String name)
      throws ValidationException {
    try {
      GroupInfo groupInfo = null;
      try {
        groupInfo = createGroupFactory.create(name)
            .apply(TopLevelResource.INSTANCE, new GroupInput());
      } catch (ResourceConflictException e) {
        // name already exists, make sure it is unique by adding a abbreviated
        // sha1
        String nameWithSha1 = name + "-" + Hashing.sha1()
            .hashString(name, Charsets.UTF_8).toString().substring(0, 7);
        log.info(
            "Failed to create group name {} because of a conflict: {}, trying to create {} instead",
            name, e.getMessage(), nameWithSha1);
        groupInfo = createGroupFactory.create(nameWithSha1)
            .apply(TopLevelResource.INSTANCE, new GroupInput());
      }
      return AccountGroup.UUID.parse(groupInfo.id);
    } catch (RestApiException | OrmException | IOException e ) {
      log.error("Failed to create project " + name + ": " + e.getMessage(), e);
      throw new ValidationException(AN_ERROR_OCCURRED_MSG);
    }
  }

  private void validateRootProject(String name, boolean permissionOnly)
      throws ValidationException {
    log.debug("validating root project name {}", name);
    if (name.contains("/")) {
      log.debug("rejecting creation of {}: name contains slashes", name);
      throw new ValidationException(String
          .format(ROOT_PROJECT_CANNOT_CONTAINS_SLASHES_MSG, documentationUrl));
    }
    if (!permissionOnly) {
      log.debug("rejecting creation of {}: missing permissions only option",
          name);
      throw new ValidationException(String
          .format(REGULAR_PROJECT_NOT_ALLOWED_AS_ROOT_MSG, documentationUrl));
    }
    log.debug("allowing creation of root project {}", name);
  }

  private void validateProject(String name, ProjectControl parentCtrl)
      throws ValidationException {
    log.debug("validating name prefix of {}", name);
    Project parent = parentCtrl.getProject();
    String prefix = parent.getName() + "/";
    if (!name.startsWith(prefix)) {
      log.debug("rejecting creation of {}: name is not starting with {}", name,
          prefix);
      throw new ValidationException(
          String.format(PROJECT_MUST_START_WITH_PARENT_NAME_MSG, prefix + name,
              documentationUrl));
    }
    if (!parentCtrl.isOwner()) {
      log.debug("rejecting creation of {}: user is not owner of {}", name,
          parent.getName());
      throw new ValidationException(
          String.format(MUST_BE_OWNER_TO_CREATE_PROJECT_MSG, parent.getName(),
              documentationUrl));
    }
    log.debug("allowing creation of project {}", name);
  }
}
