// Copyright (C) 2019 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.googlesource.gerrit.plugins.replication;

import static com.google.common.truth.Truth.assertThat;
import static java.nio.file.Files.createTempDirectory;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import com.google.common.eventbus.EventBus;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.git.WorkQueue;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.util.Providers;
import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
import java.util.stream.Collectors;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS;
import org.junit.Before;
import org.junit.Ignore;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

@Ignore
public abstract class AbstractConfigTest {
  protected final Path sitePath;
  protected final SitePaths sitePaths;
  protected final Destination.Factory destinationFactoryMock;
  protected final Path pluginDataPath;
  protected ReplicationQueue replicationQueueMock;
  protected WorkQueue workQueueMock;
  protected EventBus eventBus = new EventBus();
  protected FakeExecutorService executorService = new FakeExecutorService();
  protected ConfigParser configParser;

  static class FakeDestination extends Destination {
    public final DestinationConfiguration config;

    protected FakeDestination(DestinationConfiguration config) {
      super(injectorMock(), null, null, null, null, null, null, null, null, null, null, config);
      this.config = config;
    }

    private static Injector injectorMock() {
      Injector injector = mock(Injector.class);
      Injector childInjectorMock = mock(Injector.class);
      when(injector.createChildInjector(any(Module.class))).thenReturn(childInjectorMock);
      return injector;
    }
  }

  AbstractConfigTest() throws IOException {
    sitePath = createTempPath("site");
    sitePaths = new SitePaths(sitePath);
    pluginDataPath = createTempPath("data");
    destinationFactoryMock = mock(Destination.Factory.class);
    configParser = new ConfigParser();
  }

  @Before
  public void setup() {
    when(destinationFactoryMock.create(any(DestinationConfiguration.class)))
        .thenAnswer(
            new Answer<Destination>() {
              @Override
              public Destination answer(InvocationOnMock invocation) throws Throwable {
                return new FakeDestination((DestinationConfiguration) invocation.getArguments()[0]);
              }
            });

    replicationQueueMock = mock(ReplicationQueue.class);
    when(replicationQueueMock.isRunning()).thenReturn(Boolean.TRUE);

    workQueueMock = mock(WorkQueue.class);
    when(workQueueMock.createQueue(anyInt(), any(String.class))).thenReturn(executorService);
  }

  protected static Path createTempPath(String prefix) throws IOException {
    return createTempDirectory(prefix);
  }

  protected FileBasedConfig newReplicationConfig() {
    return newReplicationConfig("replication.config");
  }

  protected FileBasedConfig newReplicationConfig(String path) {
    FileBasedConfig replicationConfig =
        new FileBasedConfig(sitePaths.etc_dir.resolve(path).toFile(), FS.DETECTED);
    return replicationConfig;
  }

  protected void assertThatIsDestination(
      Destination destination, String remoteName, String... remoteUrls) {
    DestinationConfiguration destinationConfig = ((FakeDestination) destination).config;
    assertThat(destinationConfig.getRemoteConfig().getName()).isEqualTo(remoteName);
    assertThat(destinationConfig.getUrls()).containsExactlyElementsIn(remoteUrls);
  }

  protected void assertThatContainsDestination(
      List<Destination> destinations, String remoteName, String... remoteUrls) {
    List<Destination> matchingDestinations =
        destinations.stream()
            .filter(
                (Destination dst) ->
                    ((FakeDestination) dst).config.getRemoteConfig().getName().equals(remoteName))
            .collect(Collectors.toList());

    assertThat(matchingDestinations).isNotEmpty();

    assertThatIsDestination(matchingDestinations.get(0), remoteName, remoteUrls);
  }

  protected DestinationsCollection newDestinationsCollections(ReplicationConfig replicationConfig)
      throws ConfigInvalidException {
    return new DestinationsCollection(
        destinationFactoryMock,
        Providers.of(replicationQueueMock),
        replicationConfig,
        configParser,
        eventBus);
  }

  protected ReplicationConfig newReplicationFileBasedConfig() {
    return new ReplicationFileBasedConfig(sitePaths, pluginDataPath);
  }
}
