// Copyright (C) 2010 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.entities;

import static com.google.common.collect.ImmutableList.toImmutableList;
import static java.util.Objects.requireNonNull;

import com.google.auto.value.AutoValue;
import com.google.auto.value.extension.memoized.Memoized;
import com.google.common.collect.ImmutableList;
import com.google.gerrit.common.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.regex.Pattern;

/** Portion of a {@link Project} describing access rules. */
@AutoValue
public abstract class AccessSection implements Comparable<AccessSection> {
  /** Special name given to the global capabilities; not a valid reference. */
  public static final String GLOBAL_CAPABILITIES = "GLOBAL_CAPABILITIES";
  /** Pattern that matches all references in a project. */
  public static final String ALL = "refs/*";

  /** Pattern that matches all branches in a project. */
  public static final String HEADS = "refs/heads/*";

  /** Prefix that triggers a regular expression pattern. */
  public static final String REGEX_PREFIX = "^";

  /** Name of the access section. It could be a ref pattern or something else. */
  public abstract String getName();

  /**
   * A compiled regular expression in case {@link #getName()} is a regular expression. This is
   * memoized to save callers from compiling patterns for every use.
   */
  @Memoized
  public Optional<Pattern> getNamePattern() {
    if (isValidRefSectionName(getName())
        && getName().startsWith(REGEX_PREFIX)
        && !getName().contains("${")) {
      return Optional.of(Pattern.compile(getName()));
    }
    return Optional.empty();
  }

  public abstract ImmutableList<Permission> getPermissions();

  public static AccessSection create(String name) {
    return builder(name).build();
  }

  public static Builder builder(String name) {
    return new AutoValue_AccessSection.Builder().setName(name).setPermissions(ImmutableList.of());
  }

  /** Returns true if the name is likely to be a valid reference section name. */
  public static boolean isValidRefSectionName(String name) {
    return name.startsWith("refs/") || name.startsWith("^refs/");
  }

  @Nullable
  public Permission getPermission(String name) {
    requireNonNull(name);
    for (Permission p : getPermissions()) {
      if (p.getName().equalsIgnoreCase(name)) {
        return p;
      }
    }
    return null;
  }

  @Override
  public final int compareTo(AccessSection o) {
    return comparePattern().compareTo(o.comparePattern());
  }

  private String comparePattern() {
    if (getName().startsWith(REGEX_PREFIX)) {
      return getName().substring(REGEX_PREFIX.length());
    }
    return getName();
  }

  @Override
  public final String toString() {
    return "AccessSection[" + getName() + "]";
  }

  public Builder toBuilder() {
    Builder b = autoToBuilder();
    b.getPermissions().stream().map(Permission::toBuilder).forEach(p -> b.addPermission(p));
    return b;
  }

  protected abstract Builder autoToBuilder();

  @AutoValue.Builder
  public abstract static class Builder {
    private final List<Permission.Builder> permissionBuilders;

    protected Builder() {
      permissionBuilders = new ArrayList<>();
    }

    public abstract Builder setName(String name);

    public abstract String getName();

    public Builder modifyPermissions(Consumer<List<Permission.Builder>> modification) {
      modification.accept(permissionBuilders);
      return this;
    }

    public Builder addPermission(Permission.Builder permission) {
      requireNonNull(permission, "permission must be non-null");
      return modifyPermissions(p -> p.add(permission));
    }

    public Builder remove(Permission.Builder permission) {
      requireNonNull(permission, "permission must be non-null");
      return removePermission(permission.getName());
    }

    public Builder removePermission(String name) {
      requireNonNull(name, "name must be non-null");
      return modifyPermissions(
          p -> p.removeIf(permissionBuilder -> name.equalsIgnoreCase(permissionBuilder.getName())));
    }

    public Permission.Builder upsertPermission(String permissionName) {
      requireNonNull(permissionName, "permissionName must be non-null");

      Optional<Permission.Builder> maybePermission =
          permissionBuilders.stream()
              .filter(p -> p.getName().equalsIgnoreCase(permissionName))
              .findAny();
      if (maybePermission.isPresent()) {
        return maybePermission.get();
      }

      Permission.Builder permission = Permission.builder(permissionName);
      modifyPermissions(p -> p.add(permission));
      return permission;
    }

    public AccessSection build() {
      setPermissions(
          permissionBuilders.stream().map(Permission.Builder::build).collect(toImmutableList()));
      if (getPermissions().size()
          > getPermissions().stream()
              .map(Permission::getName)
              .map(String::toLowerCase)
              .distinct()
              .count()) {
        throw new IllegalArgumentException("duplicate permissions: " + getPermissions());
      }
      return autoBuild();
    }

    protected abstract AccessSection autoBuild();

    protected abstract ImmutableList<Permission> getPermissions();

    abstract Builder setPermissions(ImmutableList<Permission> permissions);
  }
}
