// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.execution.testDiscovery;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.annotations.SerializedName;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.io.HttpRequests;
import com.intellij.util.io.RequestBuilder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class IntellijTestDiscoveryProducer implements TestDiscoveryProducer {
  private static final String INTELLIJ_TEST_DISCOVERY_HOST = "http://intellij-test-discovery";

  @NotNull
  @Override
  public MultiMap<String, String> getDiscoveredTests(@NotNull Project project,
                                                     @NotNull String classFQName,
                                                     @NotNull String methodName,
                                                     byte frameworkId) {
    if (!ApplicationManager.getApplication().isInternal()) {
      return MultiMap.emptyInstance();
    }
    String methodFqn = classFQName + "." + methodName;
    RequestBuilder r = HttpRequests.request(INTELLIJ_TEST_DISCOVERY_HOST + "/search/tests/by-method/" + methodFqn);

    try {
      return r.connect(request -> {
        MultiMap<String, String> map = new MultiMap<>();
        TestsSearchResult result = new ObjectMapper().readValue(request.getInputStream(), TestsSearchResult.class);
        result.getTests().forEach(s -> {
          String str = s.length() > 1 && s.charAt(0) == 'j' ? s.substring(1) : s;
          String classFqn = StringUtil.substringBefore(str, "-");
          String testMethodName = StringUtil.substringAfter(str, "-");
          map.putValue(classFqn, testMethodName);
        });
        return map;
      });
    }
    catch (HttpRequests.HttpStatusException http) {
      LOG.debug("No tests found for " + methodFqn);
    }
    catch (IOException e) {
      LOG.debug(e);
    }
    return MultiMap.empty();
  }

  @Override
  public boolean isRemote() {
    return true;
  }

  @JsonInclude(JsonInclude.Include.NON_EMPTY)
  public static class TestsSearchResult {
    @Nullable
    private String method;

    @SerializedName("class")
    @JsonProperty("class")
    @Nullable
    private String className;

    private int found;

    @NotNull
    private List<String> tests = new ArrayList<>();

    @Nullable
    private String message;

    @Nullable
    public String getMethod() {
      return method;
    }

    public TestsSearchResult setMethod(String method) {
      this.method = method;
      return this;
    }

    @Nullable
    public String getClassName() {
      return className;
    }

    public TestsSearchResult setClassName(String name) {
      this.className = name;
      return this;
    }

    public int getFound() {
      return found;
    }

    @NotNull
    public List<String> getTests() {
      return tests;
    }

    public TestsSearchResult setTests(List<String> tests) {
      this.tests = tests;
      this.found = tests.size();
      return this;
    }

    @Nullable
    public String getMessage() {
      return message;
    }

    public TestsSearchResult setMessage(String message) {
      this.message = message;
      return this;
    }
  }
}

@@ -500,58 +500,8 @@
 ct;%0A
-import com.intellij.openapi.util.text.StringUtil;%0A
 impo
@@ -763,47 +763,15 @@
 til.
-ArrayList;%0Aimport java.util.Collections
+HashMap
 ;%0Aim
@@ -812,25 +812,11 @@
 til.
-stream.Collectors
+Map
 ;%0A%0Ap
@@ -1861,243 +1861,37 @@
 ach(
-s -%3E %7B%0A          String str = s.length() %3E 1 && s.charAt(0) == 'j' ? s.substring(1) : s;%0A          String classFqn = StringUtil.substringBefore(str, %22-%22);%0A          String testMethodName = StringUtil.substringAfter(str, %22-%22);%0A         
+(classFqn, testMethodName) -%3E
  map
@@ -1899,16 +1899,17 @@
 putValue
+s
 (classFq
@@ -1930,19 +1930,8 @@
 ame)
-;%0A        %7D
 );%0A 
@@ -2506,16 +2506,28 @@
  private
+ Map%3CString,
  List%3CSt
@@ -2527,24 +2527,25 @@
 List%3CString%3E
+%3E
  tests = new
@@ -2549,17 +2549,15 @@
 new 
-ArrayList
+HashMap
 %3C%3E()
@@ -3056,16 +3056,28 @@
   public
+ Map%3CString,
  List%3CSt
@@ -3077,24 +3077,25 @@
 List%3CString%3E
+%3E
  getTests() 
@@ -3161,16 +3161,37 @@
 etTests(
+@NotNull Map%3CString, 
 List%3CStr
@@ -3194,16 +3194,17 @@
 %3CString%3E
+%3E
  tests) 
@@ -3260,12 +3260,50 @@
 sts.
-size
+values().stream().mapToInt(List::size).sum
 ();%0A

update test discovery server protocol