package au.com.dius.pact.provider.junit.target;

import au.com.dius.pact.model.Interaction;
import au.com.dius.pact.model.Pact;
import au.com.dius.pact.model.PactSource;
import au.com.dius.pact.model.ProviderState;
import au.com.dius.pact.provider.ConsumerInfo;
import au.com.dius.pact.provider.PactVerification;
import au.com.dius.pact.provider.ProviderInfo;
import au.com.dius.pact.provider.ProviderVerifier;
import au.com.dius.pact.provider.junit.Provider;
import au.com.dius.pact.provider.junit.loader.PactBroker;
import au.com.dius.pact.provider.junit.loader.PactFolder;
import au.com.dius.pact.provider.junit.loader.PactFolderLoader;
import org.codehaus.groovy.runtime.MethodClosure;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Out-of-the-box implementation of {@link Target},
 * that run {@link Interaction} against message pact and verify response
 */
public class AmqpTarget extends BaseTarget {
  private List<String> packagesToScan = Collections.emptyList();

  public AmqpTarget() { }

  /**
   * Initialises the AMPQ target with the list of packages to scan
   * @param packagesToScan List of JVM packages
   */
  public AmqpTarget(List<String> packagesToScan) {
    this.packagesToScan = packagesToScan;
  }

  /**
     * {@inheritDoc}
     */
    @Override
    public void testInteraction(final String consumerName, final Interaction interaction, final PactSource source) {
      ProviderInfo provider = getProviderInfo(source);
      ConsumerInfo consumer = new ConsumerInfo(consumerName);
      ProviderVerifier verifier = setupVerifier(interaction, provider, consumer);

      Map<String, Object> failures = new HashMap<>();
      verifier.verifyResponseByInvokingProviderMethods(provider, consumer, interaction, interaction.getDescription(),
        failures);

      try {
        if (!failures.isEmpty()) {
          verifier.displayFailures(failures);
          throw getAssertionError(failures);
        }
      } finally {
        verifier.finialiseReports();
      }
    }

    protected ProviderVerifier setupVerifier(Interaction interaction, ProviderInfo provider,
                                             ConsumerInfo consumer) {
    ProviderVerifier verifier = new ProviderVerifier();
    verifier.setProjectClasspath(new MethodClosure(this, "getClassPathUrls"));

    setupReporters(verifier, provider.getName(), interaction.getDescription());

    verifier.initialiseReporters(provider);
    verifier.reportVerificationForConsumer(consumer, provider);

    if (!interaction.getProviderStates().isEmpty()) {
      for (ProviderState providerState: interaction.getProviderStates()) {
        verifier.reportStateForInteraction(providerState.getName(), provider, consumer, true);
      }
    }

    verifier.reportInteractionDescription(interaction);

    return verifier;
  }

  private URL[] getClassPathUrls() {
    return ((URLClassLoader)ClassLoader.getSystemClassLoader()).getURLs();
  }

  protected ProviderInfo getProviderInfo(PactSource source) {
    Provider provider = testClass.getAnnotation(Provider.class);
    ProviderInfo providerInfo = new ProviderInfo(provider.value());
    providerInfo.setVerificationType(PactVerification.ANNOTATED_METHOD);
    providerInfo.setPackagesToScan(packagesToScan);
    PactBroker annotation = testClass.getAnnotation(PactBroker.class);
    PactFolder folder = testClass.getAnnotation(PactFolder.class);

    if(annotation != null && annotation.host() != null) {
      List list = providerInfo.hasPactsFromPactBroker(annotation.protocol() + "://" + annotation.host() + (annotation.port() != null ? ":" + annotation.port() : ""));
      providerInfo.setConsumers(list);
    } else if (folder != null && folder.value() != null) {
      try {
        PactFolderLoader folderLoader = new PactFolderLoader(folder);
        Map<Pact, File> pactFileMap = folderLoader.loadPactsWithFiles(providerInfo.getName());
        providerInfo.setConsumers(pactFileMap.entrySet().stream()
          .map(e -> new ConsumerInfo(e.getKey().getConsumer().getName(), e.getValue()))
          .collect(Collectors.toList()));
      } catch (IOException e) {
        e.printStackTrace();
      }
    }

    return providerInfo;
  }
}

@@ -76,55 +76,150 @@
 del.
-Interaction;%0Aimport au.com.dius.pact.model.Pact
+DirectorySource;%0Aimport au.com.dius.pact.model.Interaction;%0Aimport au.com.dius.pact.model.Pact;%0Aimport au.com.dius.pact.model.PactBrokerSource
 ;%0Aim
@@ -877,24 +877,52 @@
 lassLoader;%0A
+import java.util.ArrayList;%0A
 import java.
@@ -3571,649 +3571,451 @@
 n);%0A
+%0A
     
-PactBroker annotation = testClass.getAnnotation(PactBroker.class);%0A
+if (source instanceof PactBrokerSource) %7B%0A 
     
+ 
 Pact
-Folder folder = testClass.getAnnotation(PactFolder.class);%0A%0A    if(annotation != null && annotation.host() != null) %7B%0A      List list = providerInfo.hasPactsFromPactBroker(annotation.protocol() + %22://%22 + annotation.host() + (annotation.port() != null ? %22:%22 + annotation.port() : %22%22
+BrokerSource brokerSource = (PactBrokerSource) source;%0A      providerInfo.setConsumers(brokerSource.getPacts().entrySet().stream()%0A        .flatMap(e -%3E e.getValue().stream().map(p -%3E new ConsumerInfo(e.getKey().getName(), p)
 ))
-;
 %0A      
-providerInfo.setConsumers(list);%0A    %7D else if (folder != null && folder.value() != null) %7B%0A      try %7B%0A        PactFolderLoader folderLoader = new PactFolderLoader(folder);%0A        Map%3CPact, File%3E pactFileMap = folderLoader.loadPactsWithFiles(providerInfo.getName());%0A  
+  .collect(Collectors.toList()));%0A    %7D else if (source instanceof DirectorySource) %7B%0A      DirectorySource directorySource = (DirectorySource) source;%0A
     
@@ -4046,19 +4046,34 @@
 ers(
-pactFileMap
+directorySource.getPacts()
 .ent
@@ -4085,26 +4085,24 @@
 ().stream()%0A
-  
         .map
@@ -4125,27 +4125,29 @@
 erInfo(e.get
-Key
+Value
 ().getConsum
@@ -4181,26 +4181,24 @@
 )))%0A        
-  
 .collect(Col
@@ -4218,79 +4218,17 @@
 t())
-);
 %0A      
-%7D catch (IOException e) %7B%0A        e.printStackTrace();%0A      %7D
+);
 %0A   

Update AmqpTarget to get the consumers from the pact source