// 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.google.gerrit.plugins.codeowners.acceptance.testsuite;

import com.google.gerrit.plugins.codeowners.backend.CodeOwnerBackend;
import com.google.gerrit.plugins.codeowners.backend.FindOwnersGlobMatcher;
import com.google.gerrit.plugins.codeowners.backend.GlobMatcher;
import com.google.gerrit.plugins.codeowners.backend.PathExpressionMatcher;
import com.google.gerrit.plugins.codeowners.backend.SimplePathExpressionMatcher;
import com.google.gerrit.plugins.codeowners.config.BackendConfig;
import com.google.inject.Inject;

/**
 * Class to create path expressions in integration tests.
 *
 * <p>How a path expression should be formatted depends on the {@link PathExpressionMatcher} that is
 * used by the {@link CodeOwnerBackend}. E.g. if files of a certain file type should be matched in
 * the current folder, as Java NIO glob the path expression would be written as {@code *.md} while
 * as regular expression it would be written as {@code ^[^/]*\.md}. By using this class tests can
 * avoid hard-coding a concrete path expression syntax so that they work against all {@link
 * CodeOwnerBackend}s.
 */
public class TestPathExpressions {
  private final BackendConfig backendConfig;

  @Inject
  TestPathExpressions(BackendConfig backendConfig) {
    this.backendConfig = backendConfig;
  }

  /**
   * Creates a path expression that matches all files of the given file type in the current folder.
   *
   * @param fileType the file type
   */
  public String matchFileTypeInCurrentFolder(String fileType) {
    PathExpressionMatcher pathExpressionMatcher = getPathExpressionMatcher();
    if (pathExpressionMatcher instanceof GlobMatcher
        || pathExpressionMatcher instanceof FindOwnersGlobMatcher
        || pathExpressionMatcher instanceof SimplePathExpressionMatcher) {
      return "*." + fileType;
    }
    throw new IllegalStateException(
        String.format(
            "path expression matcher %s not supported",
            pathExpressionMatcher.getClass().getName()));
  }

  /**
   * Creates a path expression that matches all files of the given subfolder.
   *
   * @param subfolder the subfolder
   */
  public String matchAllFilesInSubfolder(String subfolder) {
    PathExpressionMatcher pathExpressionMatcher = getPathExpressionMatcher();
    if (pathExpressionMatcher instanceof GlobMatcher
        || pathExpressionMatcher instanceof FindOwnersGlobMatcher) {
      return subfolder + "/**";
    } else if (pathExpressionMatcher instanceof SimplePathExpressionMatcher) {
      return subfolder + "/...";
    }
    throw new IllegalStateException(
        String.format(
            "path expression matcher %s not supported",
            pathExpressionMatcher.getClass().getName()));
  }

  private PathExpressionMatcher getPathExpressionMatcher() {
    CodeOwnerBackend defaultBackend = backendConfig.getDefaultBackend();
    return defaultBackend
        .getPathExpressionMatcher()
        .orElseThrow(
            () ->
                new IllegalStateException(
                    String.format(
                        "code owner backend %s doesn't support path expressions",
                        defaultBackend.getClass().getName())));
  }
}
