// Copyright (C) 2013 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.extensions.api.projects;

import com.google.gerrit.extensions.api.access.ProjectAccessInfo;
import com.google.gerrit.extensions.api.access.ProjectAccessInput;
import com.google.gerrit.extensions.common.ProjectInfo;
import com.google.gerrit.extensions.restapi.NotImplementedException;
import com.google.gerrit.extensions.restapi.RestApiException;
import java.util.List;

public interface ProjectApi {
  ProjectApi create() throws RestApiException;

  ProjectApi create(ProjectInput in) throws RestApiException;

  ProjectInfo get() throws RestApiException;

  String description() throws RestApiException;

  void description(DescriptionInput in) throws RestApiException;

  ProjectAccessInfo access() throws RestApiException;

  ProjectAccessInfo access(ProjectAccessInput p) throws RestApiException;

  ConfigInfo config() throws RestApiException;

  ConfigInfo config(ConfigInput in) throws RestApiException;

  ListRefsRequest<BranchInfo> branches();

  ListRefsRequest<TagInfo> tags();

  void deleteBranches(DeleteBranchesInput in) throws RestApiException;

  void deleteTags(DeleteTagsInput in) throws RestApiException;

  abstract class ListRefsRequest<T extends RefInfo> {
    protected int limit;
    protected int start;
    protected String substring;
    protected String regex;

    public abstract List<T> get() throws RestApiException;

    public ListRefsRequest<T> withLimit(int limit) {
      this.limit = limit;
      return this;
    }

    public ListRefsRequest<T> withStart(int start) {
      this.start = start;
      return this;
    }

    public ListRefsRequest<T> withSubstring(String substring) {
      this.substring = substring;
      return this;
    }

    public ListRefsRequest<T> withRegex(String regex) {
      this.regex = regex;
      return this;
    }

    public int getLimit() {
      return limit;
    }

    public int getStart() {
      return start;
    }

    public String getSubstring() {
      return substring;
    }

    public String getRegex() {
      return regex;
    }
  }

  List<ProjectInfo> children() throws RestApiException;

  List<ProjectInfo> children(boolean recursive) throws RestApiException;

  ChildProjectApi child(String name) throws RestApiException;

  /**
   * Look up a branch by refname.
   *
   * <p><strong>Note:</strong> This method eagerly reads the branch. Methods that mutate the branch
   * do not necessarily re-read the branch. Therefore, calling a getter method on an instance after
   * calling a mutation method on that same instance is not guaranteed to reflect the mutation. It
   * is not recommended to store references to {@code BranchApi} instances.
   *
   * @param ref branch name, with or without "refs/heads/" prefix.
   * @throws RestApiException if a problem occurred reading the project.
   * @return API for accessing the branch.
   */
  BranchApi branch(String ref) throws RestApiException;

  /**
   * Look up a tag by refname.
   *
   * <p>
   *
   * @param ref tag name, with or without "refs/tags/" prefix.
   * @throws RestApiException if a problem occurred reading the project.
   * @return API for accessing the tag.
   */
  TagApi tag(String ref) throws RestApiException;

  /**
   * Lookup a commit by its {@Code ObjectId} string.
   *
   * @param commit the {@Code ObjectId} string.
   * @return API for accessing the commit.
   */
  CommitApi commit(String commit) throws RestApiException;

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

    @Override
    public ProjectApi create(ProjectInput in) {
      throw new NotImplementedException();
    }

    @Override
    public ProjectInfo get() {
      throw new NotImplementedException();
    }

    @Override
    public String description() {
      throw new NotImplementedException();
    }

    @Override
    public ProjectAccessInfo access() {
      throw new NotImplementedException();
    }

    @Override
    public ConfigInfo config() {
      throw new NotImplementedException();
    }

    @Override
    public ConfigInfo config(ConfigInput in) {
      throw new NotImplementedException();
    }

    @Override
    public ProjectAccessInfo access(ProjectAccessInput p) {
      throw new NotImplementedException();
    }

    @Override
    public void description(DescriptionInput in) {
      throw new NotImplementedException();
    }

    @Override
    public ListRefsRequest<BranchInfo> branches() {
      throw new NotImplementedException();
    }

    @Override
    public ListRefsRequest<TagInfo> tags() {
      throw new NotImplementedException();
    }

    @Override
    public List<ProjectInfo> children() {
      throw new NotImplementedException();
    }

    @Override
    public List<ProjectInfo> children(boolean recursive) {
      throw new NotImplementedException();
    }

    @Override
    public ChildProjectApi child(String name) {
      throw new NotImplementedException();
    }

    @Override
    public BranchApi branch(String ref) {
      throw new NotImplementedException();
    }

    @Override
    public TagApi tag(String ref) {
      throw new NotImplementedException();
    }

    @Override
    public void deleteBranches(DeleteBranchesInput in) {
      throw new NotImplementedException();
    }

    @Override
    public void deleteTags(DeleteTagsInput in) {
      throw new NotImplementedException();
    }

    @Override
    public CommitApi commit(String commit) {
      throw new NotImplementedException();
    }
  }
}
