package nu.studer.teamcity.buildscan.connection;

import jetbrains.buildServer.serverSide.InvalidProperty;
import jetbrains.buildServer.serverSide.PropertiesProcessor;
import jetbrains.buildServer.serverSide.oauth.OAuthConnectionDescriptor;
import jetbrains.buildServer.serverSide.oauth.OAuthProvider;
import jetbrains.buildServer.web.openapi.PluginDescriptor;
import org.apache.log4j.Logger;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;

import static nu.studer.teamcity.buildscan.connection.GradleEnterpriseConnectionConstants.*;

public class GradleEnterpriseConnectionProvider extends OAuthProvider {

    private static final Logger LOGGER = Logger.getLogger("jetbrains.buildServer.BUILDSCAN");
    private static final String DEFAULT_PLUGIN_VERSIONS_RESOURCE = "default-plugin-versions.properties";

    private final PluginDescriptor descriptor;

    private static final PropertiesProcessor EMPTY_PROPERTIES_PROCESSOR = new EmptyPropertiesProcessor();

    public GradleEnterpriseConnectionProvider(PluginDescriptor pluginDescriptor) {
        super();
        this.descriptor = pluginDescriptor;
    }

    @NotNull
    @Override
    public String getType() {
        return GRADLE_ENTERPRISE_CONNECTION_PROVIDER;
    }

    @NotNull
    @Override
    public String getDisplayName() {
        return "Gradle Enterprise";
    }

    @Nullable
    @Override
    public String getEditParametersUrl() {
        return descriptor.getPluginResourcesPath("ge-connection-dialog.jsp");
    }

    @NotNull
    @Override
    public String describeConnection(@NotNull OAuthConnectionDescriptor connection) {
        Map<String, String> params = connection.getParameters();
        String description = "";

        String geUrl = params.get(GRADLE_ENTERPRISE_URL);
        if (geUrl != null) {
            description += String.format("Gradle Enterprise Url: %s\n", geUrl);
        }

        String allowUntrustedServer = params.get(ALLOW_UNTRUSTED_SERVER);
        if (allowUntrustedServer != null) {
            description += String.format("Allow Untrusted Server: %s\n", allowUntrustedServer);
        }

        String gradlePluginRepositoryUrl = params.get(GRADLE_PLUGIN_REPOSITORY_URL);
        if (gradlePluginRepositoryUrl != null) {
            description += String.format("Gradle Plugin Repository URL: %s\n", gradlePluginRepositoryUrl);
        }

        String gePluginVersion = params.get(GRADLE_ENTERPRISE_PLUGIN_VERSION);
        if (gePluginVersion != null) {
            description += String.format("Gradle Enterprise Plugin Version: %s\n", gePluginVersion);
        }

        String ccudPluginVersion = params.get(COMMON_CUSTOM_USER_DATA_PLUGIN_VERSION);
        if (ccudPluginVersion != null) {
            description += String.format("Common Custom User Data Plugin Version: %s\n", ccudPluginVersion);
        }

        String geExtensionVersion = params.get(GRADLE_ENTERPRISE_EXTENSION_VERSION);
        if (geExtensionVersion != null) {
            description += String.format("Gradle Enterprise Extension Version: %s\n", geExtensionVersion);
        }

        String ccudExtensionVersion = params.get(COMMON_CUSTOM_USER_DATA_EXTENSION_VERSION);
        if (ccudExtensionVersion != null) {
            description += String.format("Common Custom User Data Extension Version: %s\n", ccudExtensionVersion);
        }

        return description;
    }

    @Nullable
    @Override
    public Map<String, String> getDefaultProperties() {
        Properties properties = new Properties();
        Map<String, String> defaultProperties = new HashMap<>();
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(DEFAULT_PLUGIN_VERSIONS_RESOURCE);

        if (inputStream != null) {
            try {
                properties.load(inputStream);
                inputStream.close();
            } catch (IOException e) {
                LOGGER.warn("Unable to load default plugin version from " + DEFAULT_PLUGIN_VERSIONS_RESOURCE, e);
            }
        }

        for (Map.Entry<Object, Object> entry : properties.entrySet()) {
            defaultProperties.put(entry.getKey().toString(), entry.getValue().toString());
        }

        return defaultProperties;
    }

    @Nullable
    @Override
    public PropertiesProcessor getPropertiesProcessor() {
        // this can be used to invalidate properties set by the user
        // by returning empty list, no validation is done
        return EMPTY_PROPERTIES_PROCESSOR;
    }

    private static class EmptyPropertiesProcessor implements PropertiesProcessor {
        @Override
        public Collection<InvalidProperty> process(Map<String, String> properties) {
            return Collections.emptyList();
        }
    }
}

@@ -1811,16 +1811,56 @@
 tion = %22
+Gradle Enterprise Connection Settings:%5Cn
 %22;%0A%0A    
@@ -1976,32 +1976,34 @@
  String.format(%22
+* 
 Gradle Enterpris
@@ -2195,16 +2195,18 @@
 format(%22
+* 
 Allow Un
@@ -2274,250 +2274,46 @@
     
-String gradlePluginRepositoryUrl = params.get(GRADLE_PLUGIN_REPOSITORY_URL);%0A        if (gradlePluginRepositoryUrl != null) %7B%0A            description += String.format(%22Gradle Plugin Repository URL: %25s%5Cn%22, gradlePluginRepositoryUrl);%0A        %7D
+description += %22%5CnGradle Settings:%5Cn%22;
 %0A%0A  
@@ -2462,32 +2462,34 @@
  String.format(%22
+* 
 Gradle Enterpris
@@ -2704,32 +2704,34 @@
  String.format(%22
+* 
 Common Custom Us
@@ -2784,32 +2784,332 @@
 on);%0A        %7D%0A%0A
+        String gradlePluginRepositoryUrl = params.get(GRADLE_PLUGIN_REPOSITORY_URL);%0A        if (gradlePluginRepositoryUrl != null) %7B%0A            description += String.format(%22* Gradle Plugin Repository URL: %25s%5Cn%22, gradlePluginRepositoryUrl);%0A        %7D%0A%0A        description += %22%5CnMaven Settings%5Cn%22;%0A%0A
         String g
@@ -3261,16 +3261,18 @@
 format(%22
+* 
 Gradle E
@@ -3518,16 +3518,18 @@
 format(%22
+* 
 Common C

Align parameters description with the connection description categories