// Copyright (C) 2020 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.gerritforge.gerrit.globalrefdb.validation;

import com.google.common.base.Strings;
import com.google.common.collect.Sets;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.Project.NameKey;
import com.google.gerrit.server.events.Event;
import com.google.gerrit.server.events.ProjectEvent;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.util.List;
import java.util.Set;

// import com.google.gerrit.entities.AccessSection;

/**
 * Filter to match against project names to indicate whether a project should be validated against a
 * global refdb.
 *
 * <p>Filters are computed by reading the configuration of the libModule consuming this library.
 */
@Singleton
public class ProjectsFilter {

  /** The type of the pattern defining this filter */
  public enum PatternType {
    /**
     * Values starting with a caret `^` are treated as regular expressions. For the regular
     * expressions details please @see <a
     * href="https://docs.oracle.com/javase/tutorial/essential/regex/">official java
     * documentation</a>
     */
    REGEX,
    /**
     * Values that are not regular expressions and end in `*` are treated as wildcard matches.
     * Wildcards match projects whose name agrees from the beginning until the trailing `*`. So
     * `foo/b*` would match the projects `foo/b`, `foo/bar`, and `foo/baz`, but neither `foobar`,
     * nor `bar/foo/baz`.
     */
    WILDCARD,
    /**
     * Values that are neither regular expressions nor wildcards are treated as single project
     * matches. So `foo/bar` matches only the project `foo/bar`, but no other project.
     */
    EXACT_MATCH;

    public static PatternType getPatternType(String pattern) {
      // TODO: Use AccessSection
      if (pattern.startsWith("^")) {
        //      if (pattern.startsWith(AccessSection.REGEX_PREFIX)) {
        return REGEX;
      } else if (pattern.endsWith("*")) {
        return WILDCARD;
      } else {
        return EXACT_MATCH;
      }
    }
  }

  private Set<NameKey> globalProjects = Sets.newConcurrentHashSet();
  private Set<NameKey> localProjects = Sets.newConcurrentHashSet();
  private final List<String> projectPatterns;

  /**
   * Constructs a {@code ProjectsFilter} by providing the libModule configuration
   *
   * @param cfg the libModule configuration
   */
  @Inject
  public ProjectsFilter(SharedRefDbConfiguration cfg) {
    projectPatterns = cfg.projects().getPatterns();
  }

  /**
   * Given an event checks whether this project filter matches the project associated with the
   * event. Returns false for all other events.
   *
   * @see #matches(NameKey)
   * @param event the event to check against
   * @return true when it matches, false otherwise.
   */
  public boolean matches(Event event) {
    if (event == null) {
      throw new IllegalArgumentException("Event object cannot be null");
    }
    if (event instanceof ProjectEvent) {
      return matches(((ProjectEvent) event).getProjectNameKey());
    }
    return false;
  }

  /**
   * checks whether this project filter matches the projectName
   *
   * @see #matches(NameKey)
   * @param projectName the project name to check against
   * @return true when it matches, false otherwise.
   */
  public boolean matches(String projectName) {
    return matches(NameKey.parse(projectName));
  }

  /**
   * checks whether this project filter matches the project name.
   *
   * @param name the name of the project to check
   * @return true, when the project matches, false otherwise.
   */
  public boolean matches(Project.NameKey name) {
    if (name == null || Strings.isNullOrEmpty(name.get())) {
      throw new IllegalArgumentException(
          String.format("Project name cannot be null or empty, but was %s", name));
    }
    if (projectPatterns.isEmpty() || globalProjects.contains(name)) {
      return true;
    }

    if (localProjects.contains(name)) {
      return false;
    }

    String projectName = name.get();

    for (String pattern : projectPatterns) {
      if (matchesPattern(projectName, pattern)) {
        globalProjects.add(name);
        return true;
      }
    }
    localProjects.add(name);
    return false;
  }

  private boolean matchesPattern(String projectName, String pattern) {
    boolean match = false;
    switch (PatternType.getPatternType(pattern)) {
      case REGEX:
        match = projectName.matches(pattern);
        break;
      case WILDCARD:
        match = projectName.startsWith(pattern.substring(0, pattern.length() - 1));
        break;
      case EXACT_MATCH:
        match = projectName.equals(pattern);
    }
    return match;
  }
}
