// 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.annotations.VisibleForTesting;
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.ChangeDeletedEvent;
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, Event> 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 ChangeDeletedEvent) {
                  recordedEvents.put(ChangeDeletedEvent.TYPE, (ChangeDeletedEvent) e);
                } else if (e instanceof RefEvent) {
                  RefEvent event = (RefEvent) e;
                  String key =
                      refEventKey(
                          event.getType(), event.getProjectNameKey().get(), event.getRefName());
                  recordedEvents.put(key, event);
                } else {
                  recordedEvents.put(e.type, e);
                }
              }

              @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;
  }

  @VisibleForTesting
  public 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;
  }

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

  public ImmutableList<Event> getGenericEvents(String type, int expectedSize) {
    if (expectedSize == 0) {
      assertThat(recordedEvents).doesNotContainKey(type);
      return ImmutableList.of();
    }
    assertThat(recordedEvents).containsKey(type);
    ImmutableList<Event> events = FluentIterable.from(recordedEvents.get(type)).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 assertChangeDeletedEvents(String... expected) {
    ImmutableList<ChangeDeletedEvent> events = getChangeDeletedEvents(expected.length / 2);
    int i = 0;
    for (ChangeDeletedEvent event : events) {
      String id = event.change.get().id;
      assertThat(id).isEqualTo(expected[i]);
      String reviewer = event.deleter.get().email;
      assertThat(reviewer).isEqualTo(expected[i + 1]);
      i += 2;
    }
  }

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