// 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 com.googlesource.gerrit.plugins.replication.api.ConfigResource;
import com.googlesource.gerrit.plugins.replication.api.ReplicationConfig;
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 DestinationConfigParser();
  }

  @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(ConfigResource configResource)
      throws ConfigInvalidException {
    return newDestinationsCollections(
        new ReplicationConfigImpl(
            MergedConfigResource.withBaseOnly(configResource), sitePaths, pluginDataPath));
  }

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

  protected ReplicationConfigImpl newReplicationFileBasedConfig() {
    return new ReplicationConfigImpl(
        MergedConfigResource.withBaseOnly(new FileConfigResource(sitePaths)),
        sitePaths,
        pluginDataPath);
  }
}
