// Copyright (C) 2016 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;

import static com.google.common.truth.Truth.assertThat;

import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.extensions.registration.RegistrationHandle;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.data.RefUpdateAttribute;
import com.google.gerrit.server.events.ChangeMergedEvent;
import com.google.gerrit.server.events.Event;
import com.google.gerrit.server.events.RefEvent;
import com.google.gerrit.server.events.RefUpdatedEvent;
import com.google.gerrit.server.events.ReviewerDeletedEvent;
import com.google.gerrit.server.events.UserScopedEventListener;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.revwalk.RevCommit;

public class EventRecorder {
  private final RegistrationHandle eventListenerRegistration;
  private final ListMultimap<String, RefEvent> recordedEvents;

  @Singleton
  public static class Factory {
    private final DynamicSet<UserScopedEventListener> eventListeners;
    private final IdentifiedUser.GenericFactory userFactory;

    @Inject
    Factory(
        DynamicSet<UserScopedEventListener> eventListeners,
        IdentifiedUser.GenericFactory userFactory) {
      this.eventListeners = eventListeners;
      this.userFactory = userFactory;
    }

    public EventRecorder create(TestAccount user) {
      return new EventRecorder(eventListeners, userFactory.create(user.id));
    }
  }

  public EventRecorder(DynamicSet<UserScopedEventListener> eventListeners, IdentifiedUser user) {
    recordedEvents = LinkedListMultimap.create();

    eventListenerRegistration =
        eventListeners.add(
            "gerrit",
            new UserScopedEventListener() {
              @Override
              public void onEvent(Event e) {
                if (e instanceof ReviewerDeletedEvent) {
                  recordedEvents.put(ReviewerDeletedEvent.TYPE, (ReviewerDeletedEvent) e);
                } else if (e instanceof RefEvent) {
                  RefEvent event = (RefEvent) e;
                  String key =
                      refEventKey(
                          event.getType(), event.getProjectNameKey().get(), event.getRefName());
                  recordedEvents.put(key, event);
                }
              }

              @Override
              public CurrentUser getUser() {
                return user;
              }
            });
  }

  private static String refEventKey(String type, String project, String ref) {
    return String.format("%s-%s-%s", type, project, ref);
  }

  private ImmutableList<RefUpdatedEvent> getRefUpdatedEvents(
      String project, String refName, int expectedSize) {
    String key = refEventKey(RefUpdatedEvent.TYPE, project, refName);
    if (expectedSize == 0) {
      assertThat(recordedEvents).doesNotContainKey(key);
      return ImmutableList.of();
    }

    assertThat(recordedEvents).containsKey(key);
    ImmutableList<RefUpdatedEvent> events =
        FluentIterable.from(recordedEvents.get(key))
            .transform(RefUpdatedEvent.class::cast)
            .toList();
    assertThat(events).hasSize(expectedSize);
    return events;
  }

  private ImmutableList<ChangeMergedEvent> getChangeMergedEvents(
      String project, String branch, int expectedSize) {
    String key = refEventKey(ChangeMergedEvent.TYPE, project, branch);
    if (expectedSize == 0) {
      assertThat(recordedEvents).doesNotContainKey(key);
      return ImmutableList.of();
    }

    assertThat(recordedEvents).containsKey(key);
    ImmutableList<ChangeMergedEvent> events =
        FluentIterable.from(recordedEvents.get(key))
            .transform(ChangeMergedEvent.class::cast)
            .toList();
    assertThat(events).hasSize(expectedSize);
    return events;
  }

  private ImmutableList<ReviewerDeletedEvent> getReviewerDeletedEvents(int expectedSize) {
    String key = ReviewerDeletedEvent.TYPE;
    if (expectedSize == 0) {
      assertThat(recordedEvents).doesNotContainKey(key);
      return ImmutableList.of();
    }
    assertThat(recordedEvents).containsKey(key);
    ImmutableList<ReviewerDeletedEvent> events =
        FluentIterable.from(recordedEvents.get(key))
            .transform(ReviewerDeletedEvent.class::cast)
            .toList();
    assertThat(events).hasSize(expectedSize);
    return events;
  }

  public void assertNoRefUpdatedEvents(String project, String branch) throws Exception {
    getRefUpdatedEvents(project, branch, 0);
  }

  public void assertRefUpdatedEvents(String project, String branch, String... expected)
      throws Exception {
    ImmutableList<RefUpdatedEvent> events =
        getRefUpdatedEvents(project, branch, expected.length / 2);
    int i = 0;
    for (RefUpdatedEvent event : events) {
      RefUpdateAttribute actual = event.refUpdate.get();
      String oldRev = expected[i] == null ? ObjectId.zeroId().name() : expected[i];
      String newRev = expected[i + 1] == null ? ObjectId.zeroId().name() : expected[i + 1];
      assertThat(actual.oldRev).isEqualTo(oldRev);
      assertThat(actual.newRev).isEqualTo(newRev);
      i += 2;
    }
  }

  public void assertRefUpdatedEvents(String project, String branch, RevCommit... expected)
      throws Exception {
    ImmutableList<RefUpdatedEvent> events =
        getRefUpdatedEvents(project, branch, expected.length / 2);
    int i = 0;
    for (RefUpdatedEvent event : events) {
      RefUpdateAttribute actual = event.refUpdate.get();
      String oldRev = expected[i] == null ? ObjectId.zeroId().name() : expected[i].name();
      String newRev = expected[i + 1] == null ? ObjectId.zeroId().name() : expected[i + 1].name();
      assertThat(actual.oldRev).isEqualTo(oldRev);
      assertThat(actual.newRev).isEqualTo(newRev);
      i += 2;
    }
  }

  public void assertChangeMergedEvents(String project, String branch, String... expected)
      throws Exception {
    ImmutableList<ChangeMergedEvent> events =
        getChangeMergedEvents(project, branch, expected.length / 2);
    int i = 0;
    for (ChangeMergedEvent event : events) {
      String id = event.change.get().id;
      assertThat(id).isEqualTo(expected[i]);
      assertThat(event.newRev).isEqualTo(expected[i + 1]);
      i += 2;
    }
  }

  public void assertReviewerDeletedEvents(String... expected) {
    ImmutableList<ReviewerDeletedEvent> events = getReviewerDeletedEvents(expected.length / 2);
    int i = 0;
    for (ReviewerDeletedEvent event : events) {
      String id = event.change.get().id;
      assertThat(id).isEqualTo(expected[i]);
      String reviewer = event.reviewer.get().email;
      assertThat(reviewer).isEqualTo(expected[i + 1]);
      i += 2;
    }
  }

  public void close() {
    eventListenerRegistration.remove();
  }
}
