package org.apache.mesos.elasticsearch.common.util;

import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.PumpStreamHandler;
import org.apache.commons.exec.environment.EnvironmentUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.Map;

/**
 * Utilities to help with networking
 */
@SuppressWarnings("PMD.AvoidUsingHardCodedIP")
public class NetworkUtils {
    private static final Logger LOG = Logger.getLogger(NetworkUtils.class);
    public static final String DOCKER_MACHINE_IP = "docker-machine ip";
    public static final String LOCALHOST = "127.0.0.1";
    public static final String DOCKER_MACHINE_NAME = "DOCKER_MACHINE_NAME";

    public static InetAddress hostAddress() {
        try {
            return InetAddress.getLocalHost();
        } catch (UnknownHostException e) {
            LOG.error("", e);
            throw new RuntimeException("Unable to bind to local host.");
        }
    }

    public static InetSocketAddress hostSocket(int port) {
        return new InetSocketAddress(hostAddress(), port);
    }

    public static String addressToString(InetSocketAddress address, Boolean useIpAddress) {
        if (useIpAddress) {
            return "http://" + address.getAddress().getHostAddress() + ":" + address.getPort();
        } else {
            return "http://" + address.getAddress().getHostName() + ":" + address.getPort();
        }
    }

    public static String getDockerMachineName(Map<String, String> environment) {
        String envVar = DOCKER_MACHINE_NAME;
        String docker_machine_name = environment.getOrDefault(envVar, "");
        if (docker_machine_name == null || docker_machine_name.isEmpty()) {
            LOG.debug("The environmental variable DOCKER_MACHINE_NAME was not found. Using localhost.");
        }
        return docker_machine_name;
    }

    public static String getDockerHostIpAddress(Map<String, String> environment) {
        String ipAddress = LOCALHOST; // Default of localhost
        String docker_machine_name = getDockerMachineName(environment);

        if (!docker_machine_name.isEmpty()) {
            LOG.debug("Docker machine name = " + docker_machine_name);
            CommandLine commandline = CommandLine.parse(DOCKER_MACHINE_IP);
            commandline.addArgument(docker_machine_name);
            LOG.debug("Running exec: " + commandline.toString());
            try {
                ipAddress = StringUtils.strip(runCommand(commandline));
            } catch (IOException e) {
                LOG.error("Unable to run exec command to find ip address.", e);
            }
        }
        LOG.debug("Returned IP address: " + ipAddress);
        return ipAddress;
    }

    public static Map<String, String> getEnvironment() {
        Map<String, String> env = Collections.emptyMap();
        try {
            env = EnvironmentUtils.getProcEnvironment();
        } catch (IOException e) {
            LOG.error("Unable to get environmental variables", e);
        }
        return env;
    }

    public static String runCommand(CommandLine commandline) throws IOException {
        DefaultExecutor exec = new DefaultExecutor();
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        PumpStreamHandler streamHandler = new PumpStreamHandler(outputStream);
        exec.setStreamHandler(streamHandler);
        exec.execute(commandline);
        return outputStream.toString(Charset.defaultCharset().name());
    }
}
@@ -413,92 +413,9 @@
 net.
-InetAddress;%0Aimport java.net.InetSocketAddress;%0Aimport java.net.UnknownHostException
+*
 ;%0Aim
@@ -475,16 +475,46 @@
 ctions;%0A
+import java.util.Enumeration;%0A
 import j
@@ -1810,34 +1810,32 @@
 tring docker
-_m
+M
 achine
-_n
+N
 ame = enviro
@@ -1880,34 +1880,32 @@
   if (docker
-_m
+M
 achine
-_n
+N
 ame == null 
@@ -1909,34 +1909,32 @@
 ll %7C%7C docker
-_m
+M
 achine
-_n
+N
 ame.isEmpty(
@@ -2029,25 +2029,31 @@
 . Using 
-localhost
+docker0 address
 .%22);%0A   
@@ -2080,26 +2080,24 @@
 n docker
-_m
+M
 achine
-_n
+N
 ame;%0A   
@@ -2266,26 +2266,24 @@
 g docker
-_m
+M
 achine
-_n
+N
 ame = ge
@@ -2335,26 +2335,24 @@
 (!docker
-_m
+M
 achine
-_n
+N
 ame.isEm
@@ -2411,34 +2411,32 @@
 = %22 + docker
-_m
+M
 achine
-_n
+N
 ame);%0A      
@@ -2551,18 +2551,16 @@
 cker
-_m
+M
 achine
-_n
+N
 ame)
@@ -2841,32 +2841,103 @@
 ;%0A            %7D%0A
+        %7D else %7B%0A            ipAddress = getDocker0AdapterIPAddress();%0A
         %7D%0A      
@@ -3789,10 +3789,1071 @@
 );%0A    %7D
+%0A%0A    public static String getDocker0AdapterIPAddress() %7B%0A        InetAddress docker0 = getLocalAddress(%22docker0%22);%0A        if (docker0 == null) %7B%0A            LOG.error(%22Could not get address for docker0%22);%0A            return LOCALHOST;%0A        %7D else %7B%0A            return docker0.getHostAddress();%0A        %7D%0A    %7D%0A%0A    private static InetAddress getLocalAddress(String adaptorName)%7B%0A        try %7B%0A            Enumeration%3CNetworkInterface%3E b = NetworkInterface.getNetworkInterfaces();%0A            while (b.hasMoreElements()) %7B%0A                NetworkInterface networkInterface = b.nextElement();%0A                if (networkInterface.getName().equals(adaptorName)) %7B%0A                    for (InterfaceAddress f : networkInterface.getInterfaceAddresses()) %7B%0A                        if (f.getAddress().isSiteLocalAddress()) %7B%0A                            return f.getAddress();%0A                        %7D%0A                    %7D%0A                %7D%0A            %7D%0A        %7D catch (SocketException e) %7B%0A            e.printStackTrace();%0A        %7D%0A        return null;%0A    %7D
 %0A%7D

Use docker0 adaptor ip address, not localhost.