/**
 *
 * Copyright (c) 2006-2017, Speedment, Inc. All Rights Reserved.
 *
 * 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.speedment.runtime.core.internal.util;

import com.speedment.common.json.Json;
import com.speedment.common.logger.Logger;
import com.speedment.common.logger.LoggerManager;
import com.speedment.runtime.config.Dbms;
import com.speedment.runtime.config.Project;
import com.speedment.runtime.core.component.InfoComponent;
import com.speedment.runtime.core.component.ProjectComponent;
import com.speedment.runtime.core.internal.util.testing.TestSettings;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.time.Clock;
import java.time.Instant;
import java.time.ZoneId;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.toList;

/**
 * Utility class for reporting events to the statistics manager.
 *
 * @author Emil Forslund
 */
public final class Statistics {

    public enum Event {

        GUI_STARTED        ("gui-started"),
        GUI_PROJECT_LOADED ("gui-project-loaded"),
        GENERATE           ("generate"),
        NODE_STARTED       ("node-started"),
        NODE_ALIVE         ("node-alive"),
        NODE_STOPPED       ("node-stopped");

        private final String eventName;

        Event(String eventName) {
            this.eventName = eventName;
        }
    }

    private final static Logger LOGGER   = LoggerManager.getLogger(Statistics.class);
    private final static String PING_URL = "https://api.speedment.com:9020/stats";

    public static void report(final InfoComponent info,
                              final ProjectComponent projects,
                              final Event event) {

        requireNonNull(info);
        requireNonNull(projects);
        requireNonNull(event);

        if (TestSettings.isTestMode()) {
            return;
        }

        final Project project = projects.getProject();
        final Map<String, Object> ping = new HashMap<>();

        ping.put("userId", InternalEmailUtil.getUserId().toString());
        ping.put("appId", project.getAppId());
        ping.put("eventType", event.eventName);
        ping.put("productName", info.getTitle());
        ping.put("productVersion", info.getImplementationVersion());
        ping.put("databases", project.dbmses()
            .map(Dbms::getTypeName)
            .distinct()
            .collect(toList())
        );
        ping.put("emailAddress", InternalEmailUtil.getEmail());
        ping.put("computerName", System.getProperty("user.dir"));
        ping.put("dateStarted", STARTED);

        sendPostRequest(PING_URL, Json.toJson(ping));
    }
    private static void sendPostRequest(final String url, String data) {
        if (!TestSettings.isTestMode()) { // Wolkswagen Pattern

            CompletableFuture.runAsync(() -> {
                try {
                    final HttpURLConnection con = (HttpURLConnection)
                        new URL(url).openConnection();

                    con.connect();
                    con.getResponseCode(); // Might have side effects...
                    con.getResponseMessage();

                    try (final BufferedReader in = new BufferedReader(
                            new InputStreamReader(con.getInputStream()))) {
                        while (in.readLine() != null);
                    }
                } catch (final IOException ex) {
                    LOGGER.debug(ex);
                }
            });
        }
    }

    private static final long STARTED =
        Instant.now(Clock.system(ZoneId.of("UTC"))).getEpochSecond();

    /**
     * Utility classes should not be instantiated.
     */
    private Statistics() {
        throw new UnsupportedOperationException();
    }
}

@@ -1105,140 +1105,107 @@
 .io.
-BufferedReader;%0Aimport java.io.IOException;%0Aimport java.io.InputStreamReader;%0Aimport java.net.HttpURLConnection;%0Aimport java.net.URL
+*;%0Aimport java.net.HttpURLConnection;%0Aimport java.net.URL;%0Aimport java.nio.charset.StandardCharsets
 ;%0Aim
@@ -3683,136 +3683,519 @@
 con.
-connect();%0A                    con.getResp
+setRequestMethod(%22POST%22);%0A                    con.setUseCaches(false);%0A                    con.setAllowUserInteraction(false);%0A                    c
 on
+.
 se
-Code(); // Might have side effects...%0A                    con.getResponseMessage()
+tDoOutput(true);%0A%0A                    con.connect();%0A                    try (final OutputStream out = con.getOutputStream()) %7B%0A                        out.write(data.getBytes(StandardCharsets.UTF_8));%0A                        out.flush();%0A                    %7D%0A%0A                    int status = getResponseCodeFrom(con);%0A                    final String text
 ;%0A%0A 
@@ -4239,18 +4239,18 @@
 dReader 
-in
+rd
  = new B
@@ -4284,28 +4284,24 @@
             
-    
 new InputStr
@@ -4314,33 +4314,236 @@
 der(
-con.getInputStream()))) %7B
+status %3E= 400%0A                            ? con.getErrorStream()%0A                            : con.getInputStream()))) %7B%0A%0A                        final StringBuilder sb = new StringBuilder();%0A                        String line;
 %0A   
@@ -4570,18 +4570,26 @@
  while (
-in
+(line = rd
 .readLin
@@ -4591,16 +4591,17 @@
 adLine()
+)
  != null
@@ -4601,18 +4601,67 @@
 != null)
-;%0A
+ %7B%0A                            sb.append(line);%0A   
         
@@ -4676,129 +4676,525 @@
     
+ 
 %7D%0A
-                %7D catch (final IOException ex) %7B%0A                    LOGGER.debug(ex);%0A                %7D%0A            %7D)
+%0A                        text = sb.toString();%0A                    %7D%0A%0A                    LOGGER.debug(%22Statistics response %25d: %25s%22, status, text);%0A                %7D catch (final IOException ex) %7B%0A                    LOGGER.debug(ex);%0A                %7D%0A            %7D);%0A        %7D%0A    %7D%0A%0A    private static int getResponseCodeFrom(final HttpURLConnection conn)%0A    throws IOException %7B%0A        try %7B%0A            return conn.getResponseCode();%0A        %7D catch (final FileNotFoundException ex) %7B%0A            return 404
 ;%0A  

Use POST when sending statistics