/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.aries.containers.docker.local.impl;

import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.regex.Pattern;
import java.util.stream.Stream;

import org.apache.aries.containers.Container;
import org.apache.aries.containers.HealthCheck;
import org.apache.aries.containers.Service;
import org.apache.aries.containers.ServiceConfig;
import org.apache.aries.containers.ServiceManager;
import org.apache.felix.utils.json.JSONParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LocalDockerServiceManager implements ServiceManager {
    static final Logger LOG = LoggerFactory.getLogger(LocalDockerServiceManager.class);
    static final String SERVICE_NAME_LABEL = "org.apache.aries.containers.service.name";

    private static final String DOCKER_MACHINE_VM_NAME = System.getenv("DOCKER_MACHINE_NAME");
    private static final boolean CHECK_DOCKER_MACHINE = Stream
            .of(System.getenv("PATH").split(Pattern.quote(File.pathSeparator)))
            .map(Paths::get)
            .anyMatch(path -> Files.exists(path.resolve("docker-machine")));

    private static final boolean USE_DOCKER_MACHINE = (DOCKER_MACHINE_VM_NAME != null) && CHECK_DOCKER_MACHINE;
    static final String CONTAINER_HOST;
    static {
        if (USE_DOCKER_MACHINE) {
            try {
                CONTAINER_HOST = ProcessRunner.waitFor(ProcessRunner.run("docker-machine", "ip", DOCKER_MACHINE_VM_NAME));
            } catch (IOException e) {
                throw new RuntimeException("Problem invoking docker-machine", e);
            }
        } else {
            CONTAINER_HOST = "localhost";
        }
    }

    private final LocalDockerController docker;
    final ConcurrentMap<String, Service> services =
            new ConcurrentHashMap<>();

    public LocalDockerServiceManager() {
        this(new LocalDockerController());
    }

    LocalDockerServiceManager(LocalDockerController docker) {
        this.docker = docker;
    }

    List<String> getDockerIDs(ServiceConfig config) throws IOException {
        return docker.ps(SERVICE_NAME_LABEL + "=" + config.getServiceName());
    }

    @Override
    public Service getService(ServiceConfig config) throws Exception {
        Service existingService = services.get(config.getServiceName());
        if (existingService != null)
            return existingService;

        List<ContainerImpl> containers = discoverContainers(config);
        if (containers.size() == 0)
            containers = createContainers(config);

        ServiceImpl svc = new ServiceImpl(config, this, containers);
        for (ContainerImpl c : containers) {
            c.setService(svc);
        }

        services.put(config.getServiceName(), svc);

        return svc;
    }

    private List<ContainerImpl> createContainers(ServiceConfig config) throws Exception {
        List<ContainerImpl> containers = new ArrayList<>();

        for (int i=0; i<config.getRequestedInstances(); i++) {
            containers.add(createDockerContainer(config));
        }

        return containers;
    }

    ContainerImpl createDockerContainer(ServiceConfig config) throws Exception {
        List<String> command = new ArrayList<>();
        command.add("-d");
        command.add("-l");
        command.add(SERVICE_NAME_LABEL + "=" + config.getServiceName());

        String ep = config.getEntryPoint();
        if (ep != null) {
            command.add("--entrypoint");
            command.add(ep);
        }

        Map<Integer, Integer> ports = new HashMap<>();
        for (Integer p : config.getContainerPorts()) {
            command.add("-p");
            int freePort = getFreePort();
            command.add(freePort + ":" + p);
            ports.put(p, freePort);

        }

        for(Map.Entry<String, String> entry : config.getEnvVars().entrySet()) {
            command.add("-e");
            command.add(entry.getKey() + '=' + entry.getValue());
        }

        command.add("--cpus");
        command.add("" + config.getRequestedCpuUnits() + "");

        command.add("-m");
        command.add("" + ((int) config.getRequestedMemory()) + "m");

        command.add(config.getContainerImage());
        command.addAll(Arrays.asList(config.getCommandLine()));

        if (config.getHealthChecks().size() > 0) {
            // Only one healthcheck supported
            HealthCheck hc = config.getHealthChecks().get(0);
            if (hc.getType() != HealthCheck.Type.COMMAND) {
                throw new UnsupportedOperationException("Health check of type " + hc.getType() +
                        " not supported. Docker only supports health checks of type COMMAND");
            }

            command.add("--health-cmd");
            command.add(hc.getParameters());
            command.add("--health-interval");
            command.add(hc.getInterval() + "s");
            command.add("--health-retries");
            command.add("" + hc.getMaxFailures());
// TODO Add this when docker supports it in a release.
//            command.add("--health-start-period");
//            command.add(hc.getGracePeriod() + "s");
            command.add("--health-timeout");
            command.add(hc.getTimeout() + "s");
        }

        DockerContainerInfo info = docker.run(command);

        return new ContainerImpl(info.getID(), info.getIP(), ports);
    }

    public void destroyDockerContainer(String id, boolean remove) throws Exception {
        if (remove) {
            docker.remove(id);
        } else {
            docker.kill(id);
        }
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    List<ContainerImpl> discoverContainers(ServiceConfig config) throws IOException {
        List<ContainerImpl> res = new ArrayList<>();
        List<String> ids = getDockerIDs(config);
        if (ids.size() == 0)
            return Collections.emptyList();

        String infoJSON = docker.inspect(ids);
        List<Object> data = new JSONParser(infoJSON).getParsedList();
        for (Object d : data) {
            if (!(d instanceof Map))
                continue;

            Map m = (Map) d;
            Object ns = m.get("NetworkSettings");
            Map<Integer, Integer> ports = new HashMap<>();
            if (ns instanceof Map) {
                Object pd = ((Map) ns).get("Ports");
                if (pd instanceof Map) {
                    Map pm = (Map) pd;
                    for(Map.Entry entry : (Set<Map.Entry>) pm.entrySet()) {
                        try {
                            String key = entry.getKey().toString();
                            int idx = key.indexOf('/');
                            if (idx > 0)
                                key = key.substring(0, idx);
                            int containerPort = Integer.parseInt(key);
                            int hostPort = -1;
                            for (Object val : (List) entry.getValue()) {
                                if (val instanceof Map) {
                                    hostPort = Integer.parseInt(((Map) val).get("HostPort").toString());
                                }
                            }

                            if (hostPort != -1) {
                                ports.put(containerPort, hostPort);
                            }
                        } catch (Exception nfe) {
                            // ignore parsing exceptions, try next one
                        }
                    }
                }
            }
            // TODO check that the settings match!
            res.add(new ContainerImpl(m.get("Id").toString(), LocalDockerServiceManager.getContainerHost(), ports));
        }
        return res;
    }

    private int getFreePort() throws IOException {
        try (ServerSocket ss = new ServerSocket(0)) {
            return ss.getLocalPort();
        }
    }

    public static String getContainerHost() {
        return CONTAINER_HOST;
    }

    @Override
    @SuppressWarnings("rawtypes")
    public Set<String> listServices() throws Exception {
        Set<String> res = new HashSet<>();
        List<String> ids = docker.ps(SERVICE_NAME_LABEL);

        for (Service svc : services.values()) {
            res.add(svc.getConfiguration().getServiceName());
            for (Container c : svc.listContainers()) {
                ids.remove(c.getID());
            }
        }

        String json = docker.inspect(ids);
        for (Object data : new JSONParser(json).getParsedList()) {
            // These are services that have been launched previously and are not internally synced yet
            if (!(data instanceof Map)) {
                continue;
            }

            Object cd = ((Map) data).get("Config");
            if (cd instanceof Map) {
                Object ld = ((Map) cd).get("Labels");
                if (ld instanceof Map) {
                    Object serviceName = ((Map) ld).get(SERVICE_NAME_LABEL);
                    if (serviceName instanceof String) {
                        res.add((String) serviceName);
                    }
                }
            }
        }

        return res;
    }
}
