// 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.acceptance.testsuite.change;

import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
import com.google.gerrit.acceptance.testsuite.ThrowingFunction;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.Project;
import com.google.gerrit.server.edit.tree.TreeModification;
import java.util.Optional;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.merge.MergeStrategy;

/** Initial attributes of the change. If not provided, arbitrary values will be used. */
@AutoValue
public abstract class TestChangeCreation {
  public abstract Optional<Project.NameKey> project();

  public abstract String branch();

  public abstract Optional<Account.Id> owner();

  public abstract String commitMessage();

  public abstract ImmutableList<TreeModification> treeModifications();

  public abstract Optional<ImmutableList<TestCommitIdentifier>> parents();

  public abstract MergeStrategy mergeStrategy();

  abstract ThrowingFunction<TestChangeCreation, Change.Id> changeCreator();

  public static Builder builder(ThrowingFunction<TestChangeCreation, Change.Id> changeCreator) {
    return new AutoValue_TestChangeCreation.Builder()
        .changeCreator(changeCreator)
        .branch(Constants.R_HEADS + Constants.MASTER)
        .commitMessage("A test change")
        // Which value we choose here doesn't matter. All relevant code paths set the desired value.
        .mergeStrategy(MergeStrategy.OURS);
  }

  @AutoValue.Builder
  public abstract static class Builder {
    /** Target project/Repository of the change. Must be an existing project. */
    public abstract Builder project(Project.NameKey project);

    /**
     * Target branch of the change. Neither needs to exist nor needs to point to an actual commit.
     */
    public abstract Builder branch(String branch);

    /** The change owner. Must be an existing user account. */
    public abstract Builder owner(Account.Id owner);

    /**
     * The commit message. The message may contain a {@code Change-Id} footer but does not need to.
     * If the footer is absent, it will be generated.
     */
    public abstract Builder commitMessage(String commitMessage);

    /** Modified file of the change. The file content is specified via the returned builder. */
    public FileContentBuilder<Builder> file(String filePath) {
      return new FileContentBuilder<>(this, filePath, treeModificationsBuilder()::add);
    }

    abstract ImmutableList.Builder<TreeModification> treeModificationsBuilder();

    /**
     * Parent commit of the change. The commit can be specified via various means in the returned
     * builder.
     */
    public ParentBuilder<Builder> childOf() {
      return new ParentBuilder<>(parentCommit -> parents(ImmutableList.of(parentCommit)));
    }

    /**
     * Parent commits of the change. Each parent commit can be specified via various means in the
     * returned builder. The order of the parents matters and is preserved (first parent commit in
     * fluent change -> first parent of the change).
     *
     * <p>This method will automatically merge the parent commits and use the resulting commit as
     * base for the change. Use {@link #file(String)} for additional file adjustments on top of that
     * merge commit.
     *
     * <p><strong>Note:</strong> If this method fails with a merge conflict, use {@link
     * #mergeOfButBaseOnFirst()} instead and specify all other necessary file contents manually via
     * {@link #file(String)}.
     */
    public ParentBuilder<MultipleParentBuilder<Builder>> mergeOf() {
      return new ParentBuilder<>(parent -> mergeBuilder(MergeStrategy.RECURSIVE, parent));
    }

    /**
     * Parent commits of the change. Each parent commit can be specified via various means in the
     * returned builder. The order of the parents matters and is preserved (first parent commit in
     * fluent change -> first parent of the change).
     *
     * <p>This method will use the first specified parent commit as base for the resulting change.
     * This approach is especially useful if merging the parents is not possible.
     */
    public ParentBuilder<MultipleParentBuilder<Builder>> mergeOfButBaseOnFirst() {
      return new ParentBuilder<>(parent -> mergeBuilder(MergeStrategy.OURS, parent));
    }

    MultipleParentBuilder<Builder> mergeBuilder(
        MergeStrategy mergeStrategy, TestCommitIdentifier parent) {
      mergeStrategy(mergeStrategy);
      return new MultipleParentBuilder<>(this::parents, parent);
    }

    abstract Builder parents(ImmutableList<TestCommitIdentifier> parents);

    abstract Builder mergeStrategy(MergeStrategy mergeStrategy);

    abstract Builder changeCreator(ThrowingFunction<TestChangeCreation, Change.Id> changeCreator);

    abstract TestChangeCreation autoBuild();

    /**
     * Creates the change.
     *
     * @return the {@code Change.Id} of the created change
     */
    public Change.Id create() {
      TestChangeCreation changeUpdate = autoBuild();
      return changeUpdate.changeCreator().applyAndThrowSilently(changeUpdate);
    }
  }
}
