// Copyright (C) 2018 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.git.testing;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.truth.Truth.assertAbout;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.common.truth.FailureMetadata;
import com.google.common.truth.StreamSubject;
import com.google.common.truth.Subject;
import com.google.common.truth.Truth;
import com.google.gerrit.common.Nullable;
import org.eclipse.jgit.transport.PushResult;
import org.eclipse.jgit.transport.RemoteRefUpdate;

public class PushResultSubject extends Subject<PushResultSubject, PushResult> {
  public static PushResultSubject assertThat(PushResult actual) {
    return assertAbout(PushResultSubject::new).that(actual);
  }

  private PushResultSubject(FailureMetadata metadata, PushResult actual) {
    super(metadata, actual);
  }

  public void hasNoMessages() {
    check()
        .withMessage("expected no messages")
        .that(Strings.nullToEmpty(trimMessages()))
        .isEqualTo("");
  }

  public void hasMessages(String... expectedLines) {
    checkArgument(expectedLines.length > 0, "use hasNoMessages()");
    isNotNull();
    check("messages()").that(trimMessages()).isEqualTo(String.join("\n", expectedLines));
  }

  public void containsMessages(String... expectedLines) {
    checkArgument(expectedLines.length > 0, "use hasNoMessages()");
    isNotNull();
    Iterable<String> got = Splitter.on("\n").split(trimMessages());
    check("messages()").that(got).containsAllIn(expectedLines).inOrder();
  }

  private String trimMessages() {
    return trimMessages(actual().getMessages());
  }

  @VisibleForTesting
  @Nullable
  static String trimMessages(@Nullable String msg) {
    if (msg == null) {
      return null;
    }
    int idx = msg.indexOf("Processing changes:");
    if (idx >= 0) {
      msg = msg.substring(0, idx);
    }
    return msg.trim();
  }

  public void hasProcessed(ImmutableMap<String, Integer> expected) {
    ImmutableMap<String, Integer> actual;
    String messages = actual().getMessages();
    try {
      actual = parseProcessed(messages);
    } catch (RuntimeException e) {
      Truth.assert_()
          .fail(
              "failed to parse \"Processing changes\" line from messages: %s\n%s",
              messages, Throwables.getStackTraceAsString(e));
      return;
    }
    check("processedCommands()").that(actual).containsExactlyEntriesIn(expected).inOrder();
  }

  @VisibleForTesting
  static ImmutableMap<String, Integer> parseProcessed(@Nullable String messages) {
    if (messages == null) {
      return ImmutableMap.of();
    }
    String toSplit = messages.trim();
    String prefix = "Processing changes: ";
    int idx = toSplit.lastIndexOf(prefix);
    if (idx < 0) {
      return ImmutableMap.of();
    }
    toSplit = toSplit.substring(idx + prefix.length());
    if (toSplit.equals("done")) {
      return ImmutableMap.of();
    }
    String done = ", done";
    if (toSplit.endsWith(done)) {
      toSplit = toSplit.substring(0, toSplit.length() - done.length());
    }
    return ImmutableMap.copyOf(
        Maps.transformValues(
            Splitter.on(',').trimResults().withKeyValueSeparator(':').split(toSplit),
            // trimResults() doesn't trim values in the map.
            v -> Integer.parseInt(v.trim())));
  }

  public RemoteRefUpdateSubject ref(String refName) {
    return assertAbout(
            (FailureMetadata m, RemoteRefUpdate a) -> new RemoteRefUpdateSubject(refName, m, a))
        .that(actual().getRemoteUpdate(refName));
  }

  public RemoteRefUpdateSubject onlyRef(String refName) {
    check("setOfRefs()")
        .about(StreamSubject.streams())
        .that(actual().getRemoteUpdates().stream().map(RemoteRefUpdate::getRemoteName))
        .named("set of refs")
        .containsExactly(refName);
    return ref(refName);
  }

  public static class RemoteRefUpdateSubject
      extends Subject<RemoteRefUpdateSubject, RemoteRefUpdate> {
    private final String refName;

    private RemoteRefUpdateSubject(
        String refName, FailureMetadata metadata, RemoteRefUpdate actual) {
      super(metadata, actual);
      this.refName = refName;
      named("ref update for %s", refName).isNotNull();
    }

    public void hasStatus(RemoteRefUpdate.Status status) {
      RemoteRefUpdate u = actual();
      Truth.assertThat(u.getStatus())
          .named(
              "status of ref update for %s%s",
              refName, u.getMessage() != null ? ": " + u.getMessage() : "")
          .isEqualTo(status);
    }

    public void hasNoMessage() {
      Truth.assertThat(actual().getMessage())
          .named("message of ref update for %s", refName)
          .isNull();
    }

    public void hasMessage(String expected) {
      Truth.assertThat(actual().getMessage())
          .named("message of ref update for %s", refName)
          .isEqualTo(expected);
    }

    public void isOk() {
      hasStatus(RemoteRefUpdate.Status.OK);
    }

    public void isRejected(String expectedMessage) {
      hasStatus(RemoteRefUpdate.Status.REJECTED_OTHER_REASON);
      hasMessage(expectedMessage);
    }
  }
}
