// 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.api;

import static java.util.Objects.requireNonNull;

import com.google.common.collect.ImmutableSet;
import com.google.gerrit.extensions.client.ListAccountsOption;
import com.google.gerrit.extensions.restapi.NotImplementedException;
import com.google.gerrit.extensions.restapi.RestApiException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.Optional;
import java.util.Set;

/**
 * Java API for code owners in a branch or change revision.
 *
 * <p>To create an instance for a branch or change revision use {@code CodeOwnersFactory}.
 */
public interface CodeOwners {
  /** Query code owners for a path. */
  QueryRequest query();

  /**
   * Request to query code owners for a path.
   *
   * <p>Allows to set parameters on the request before executing it by calling {@link #get(Path)} or
   * {@link #get(String)}.
   */
  abstract class QueryRequest {
    private Set<ListAccountsOption> options = EnumSet.noneOf(ListAccountsOption.class);
    private Integer limit;
    private String revision;
    private Long seed;

    /**
     * Lists the code owners for the given path.
     *
     * @param path the path for which the code owners should be returned, the path may or may not
     *     exist
     * @return the code owners for the given path
     */
    public abstract CodeOwnersInfo get(Path path) throws RestApiException;

    /**
     * Lists the code owners for the given path.
     *
     * @param path the path for which the code owners should be returned, the path may or may not
     *     exist
     * @return the code owners for the given path
     */
    public CodeOwnersInfo get(String path) throws RestApiException {
      return get(Paths.get(path));
    }

    /**
     * Adds {@link ListAccountsOption} options on the request to control which account fields should
     * be populated in the {@link CodeOwnerInfo#account} field of the returned {@link
     * CodeOwnerInfo}s.
     *
     * <p>Appends to the options which have been set so far.
     */
    public QueryRequest withOptions(
        ListAccountsOption option, ListAccountsOption... furtherOptions) {
      this.options.add(requireNonNull(option, "option"));
      this.options.addAll(Arrays.asList(requireNonNull(furtherOptions, "furtherOptions")));
      return this;
    }

    /**
     * Sets a limit on the number of code owners that should be returned.
     *
     * @param limit the limit
     */
    public QueryRequest withLimit(int limit) {
      this.limit = limit;
      return this;
    }

    /**
     * Sets the seed that should be used to shuffle code owners that have the same score.
     *
     * @param seed seed that should be used to shuffle code owners that have the same score
     */
    public QueryRequest withSeed(long seed) {
      this.seed = seed;
      return this;
    }

    /**
     * Sets the branch revision from which the code owner configs should be read.
     *
     * <p>Not supported for querying code owners for a path in a change.
     *
     * @param revision the revision from which the code owner configs should be read
     */
    public QueryRequest forRevision(String revision) {
      this.revision = revision;
      return this;
    }

    /** Returns the {@link ListAccountsOption} options which have been set on the request. */
    public ImmutableSet<ListAccountsOption> getOptions() {
      return ImmutableSet.copyOf(options);
    }

    /** Returns the limit which has been set on the request. */
    public Optional<Integer> getLimit() {
      return Optional.ofNullable(limit);
    }

    /** Returns the seed that should be used to shuffle code owners that have the same score. */
    public Optional<Long> getSeed() {
      return Optional.ofNullable(seed);
    }

    /** Returns the branch revision from which the code owner configs should be read. */
    public Optional<String> getRevision() {
      return Optional.ofNullable(revision);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder(getClass().getSimpleName()).append('{');
      if (!options.isEmpty()) {
        sb.append("options=").append(options);
      }
      sb.append('}');
      return sb.toString();
    }
  }

  /**
   * A default implementation which allows source compatibility when adding new methods to the
   * interface.
   */
  class NotImplemented implements CodeOwners {
    @Override
    public QueryRequest query() {
      throw new NotImplementedException();
    }
  }
}
