package com.ag.secp.platform.common;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.spotify.docker.client.DefaultDockerClient;
import com.spotify.docker.client.DockerClient;
import com.spotify.docker.client.LogStream;
import com.spotify.docker.client.exceptions.DockerException;
import com.spotify.docker.client.messages.*;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.*;

import static java.util.Collections.singletonList;


/**
 * Created by shaoqiang on 2017/5/8.
 */
@Component
public class DockerCommon {
    @Autowired
    SqlSessionTemplate sqlSessionTemplate;

    DockerClient docker;


    public DockerCommon() {

        try {
             // docker = new DefaultDockerClient("unix:///var/run/docker.sock");
            docker = DefaultDockerClient.fromEnv().build();
        }catch (Exception e){
            e.printStackTrace();
        }
    }


    /**
     * 把long 转换成 日期 再转换成String类型
     */
    public String transferLongToDate(String dateFormat, Long millSec) {
        /*SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
        Date date = new Date(millSec);
        return sdf.format(date);*/

        Long timestamp = millSec * 1000;
        String date = new java.text.SimpleDateFormat(dateFormat).format(new java.util.Date(timestamp));
        return date;
    }

    /**
     * 获取容器
     *
     * @return
     */
    public List listContainer() {
        Map dataMap = new HashMap();
        //List listcontainer = DaoUtil.selectList("agCommon.listcontainer", dataMap);
        List listcontainer = sqlSessionTemplate.selectList("agCommon.listcontainer",dataMap);
        List data = new ArrayList();
        try {
            List<Container> containers = docker.listContainers(DockerClient.ListContainersParam.allContainers());


            for (int a = 0; a < listcontainer.size(); a++) {

                Map da = (Map) listcontainer.get(a);
                String containername = da.get("NAME").toString();


                for (int i = 0; i < containers.size(); i++) {
                    DockerBean bean = new DockerBean();
                    Container container = containers.get(i);
                    String state = container.state();//????
                    String image = container.image();//????
                    com.google.common.collect.ImmutableList<String> listdata = container.names();
                    String names = listdata.get(0).toString();


               /* com.google.common.collect.ImmutableList<String> listdata = container.names();
                String names = listdata.get(0).toString();
                //  com.google.common.collect.ImmutableSet<AttachedNetwork> networks = container.networkSettings().networks().asMultimap();
                Map map = container.networkSettings().networks().asMultimap().asMap();

                Iterator<Map.Entry<Integer, String>> it = map.entrySet().iterator();
                while (it.hasNext()) {
                    Map.Entry<Integer, String> entry = it.next();
                    System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
                }

                String ipaddress = "";
                //((AttachedNetwork) networks.toArray()[0]).ipAddress();//ip??
                */


                    String dates = transferLongToDate("yyyy-MM-dd HH:mm:ss", (Long) container.created());
                    names = names.substring(1, names.length());
                    //containername = "/" + containername;
                    if (containername.equals(names)) {
                        bean.setContainerid(container.id());
                        bean.setIpaddress(da.get("NETWORK_IP").toString());
                        bean.setImage(image);
                        bean.setState(state);
                        bean.setDates(dates);
                        bean.setNames(names);
                        data.add(bean);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return data;
    }


    /**
     * 容器监控信息写入
     */
    public void insertContainerstates() {
        try {
            List<Container> containers = docker.listContainers();
            for (int a = 0; a < containers.size(); a++) {

                Container container = containers.get(a);

                String datastring[] = getContainerStatus(container.id());
                Map dataMap=new HashMap();
                dataMap.put("cpuprecnt",datastring[0]);
                dataMap.put("memory",datastring[1]);
                dataMap.put("containerid",container.id());
                //DaoUtil.insert("agCommon.insertdockerlog",dataMap);
                sqlSessionTemplate.insert("agCommon.insertdockerlog",dataMap);
            }
        } catch (Exception e) {

        }

    }


    /**
     * 获取容器状态
     *
     * @param id
     */
    public String[] getContainerStatus(String id) {

        // final ContainerInfo info = docker.inspectContainer(id);
        //docker.createNetwork()
        // info.
        try {
            ContainerStats stats = docker.stats(id);
            CpuStats cpuStats = stats.cpuStats();
            cpuStats.cpuUsage();


           /* Object data[]=cpuStats.cpuUsage().percpuUsage().asList().toArray();
            long usagecount=0;
            for(int i=0;i<data.length;i++){

                usagecount=usagecount+ Long.parseLong(data[i].toString());
            }*/
            long totalcpu = cpuStats.cpuUsage().totalUsage().longValue();

            long systemCpuUsage = cpuStats.systemCpuUsage().longValue();
            double percent = BigDecimal.valueOf(totalcpu).divide(BigDecimal.valueOf(systemCpuUsage), 4, BigDecimal.ROUND_HALF_UP).doubleValue();

            System.out.println(percent * 100);

            long memoryuse = stats.memoryStats().usage();

            long dive = 1024 * 1024;

            double memory = BigDecimal.valueOf(memoryuse).divide(BigDecimal.valueOf(dive), 4, BigDecimal.ROUND_HALF_UP).doubleValue();


            String data[] = new String[3];
            data[0] = String.valueOf(percent*100);
            data[1] = String.valueOf(memory);
            return data;
        } catch (DockerException e) {
            e.printStackTrace();
            return null;
        } catch (InterruptedException e) {
            e.printStackTrace();
            return null;
        }

    }

    /**
     * 执行命令
     * @param id
     * @param cmd
     */
    public void execcmd(String id,String cmd){
        //cmd="/home/soft/zookeeper-3.4.8/bin/zkServer.sh start";
        //cmd="/usr/bin/mongod"
        try {
            final String[] command = {"sh", "-c", cmd};
            final ExecCreation execCreation = docker.execCreate(
                    id, command, DockerClient.ExecCreateParam.attachStdout(),
                    DockerClient.ExecCreateParam.attachStderr());
            final LogStream output = docker.execStart(execCreation.id());
            final String execOutput = output.readFully();
            System.out.println(execOutput);
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 执行容器命令
     *
     * @throws DockerException
     * @throws InterruptedException
     */
    public void execContainerCmd(String cmds,String containerid) throws DockerException, InterruptedException {
        String[] command = {"sh", "-c",cmds};

        docker.startContainer(containerid);
        ExecCreation execCreation = docker.execCreate(
                containerid, command, DockerClient.ExecCreateParam.attachStdout(),
                DockerClient.ExecCreateParam.attachStderr());
        LogStream output = docker.execStart(execCreation.id());
        String execOutput = output.readFully();
        System.out.println(execOutput);

    }

    public static void main(String args[]) {

        try {
            final DockerClient docker = DefaultDockerClient.fromEnv().build();


            //??docker

/*
//            DockerClient docker = DefaultDockerClient.builder()
//                    .uri(URI.create("http://192.168.1.203:4243"))
//                    .build();


            final List<Container> containers = docker.listContainers();

            Container container11 = containers.get(0);
            com.google.common.collect.ImmutableSet<AttachedNetwork> networks = container11.networkSettings().networks().asMultimap().get("bridge");
            String ipaddress = ((AttachedNetwork) networks.toArray()[0]).ipAddress();

            //AttachedNetwork networksa=container11.networkSettings().networks().asMultimap().get("bridge");
            //container11.networkSettings().networks().asMultimap().
            System.out.println(containers.size());

            final ContainerConfig config = ContainerConfig.builder()
                    .image("ubuntu").cmd("sh", "-c", "while :; do sleep 1; done")
                    .build();


            //  final ContainerCreation container = docker.createContainer(config);
            ContainerCreation container = docker.createContainer(config, "ubunt22112aaa33015");
            //????
            docker.startContainer(container.id());

            final List<Image> images = docker.listImages();
            final ContainerInfo info = docker.inspectContainer(container.id());
            //docker.createNetwork()
            // info.
            final ContainerStats stats = docker.stats(container.id());


            System.out.println("===" + info.state());

            final List<Container> containersa = docker.listContainers();
            System.out.println(containersa.size());*/


// Bind container ports to host ports
            final String[] ports = {"80", "22"};
            final Map<String, List<PortBinding>> portBindings = new HashMap<>();
            for (String port : ports) {
                List<PortBinding> hostPorts = new ArrayList<>();
                hostPorts.add(PortBinding.of("0.0.0.0", port));
                portBindings.put(port, hostPorts);
            }

// Bind container port 443 to an automatically allocated available host port.
            List<PortBinding> randomPort = new ArrayList<>();
            randomPort.add(PortBinding.randomPort("0.0.0.0"));
            portBindings.put("443", randomPort);

            final HostConfig hostConfig = HostConfig.builder().portBindings(portBindings).build();


            /**
             * network
             */
            final String networkName = "abbb";
            final IpamConfig ipamConfig =
                    IpamConfig.create("192.168.0.0/24", "192.168.0.0/24", "192.168.0.1");
            final Ipam ipam = Ipam.builder()
                    .driver("default")
                    .config(singletonList(ipamConfig))
                    .build();
            final Map<String, String> labels = ImmutableMap.of(
                    "name", "starship", "foo", "bar");
            NetworkConfig networkConfig =
                    NetworkConfig.builder().name(networkName).driver("bridge").checkDuplicate(true).ipam(ipam)
                            .internal(false).enableIPv6(false).labels(labels)
                            .build();
            // NetworkingConfig coni=NetworkingConfig.create();


// Create container with exposed ports
            final ContainerConfig containerConfig = ContainerConfig.builder()
                    .hostConfig(hostConfig)
                    .image("dockerzook").exposedPorts(ports)
                    .cmd("sh", "-c", "while :; do sleep 1; done")
                    .build();

            final ContainerCreation creation = docker.createContainer(containerConfig);
            final String id = creation.id();

// Inspect container
            final ContainerInfo info = docker.inspectContainer(id);

// Start container
            docker.startContainer(id);


            //  String id="6047f33335b1";
// Exec command inside running container with attached STDOUT and STDERR
//final String[] command = {"bash", "-c", "ls"};
            final String[] command = {"sh", "-c", "/home/soft/zookeeper-3.4.8/bin/zkServer.sh start"};
            final ExecCreation execCreation = docker.execCreate(
                    id, command, DockerClient.ExecCreateParam.attachStdout(),
                    DockerClient.ExecCreateParam.attachStderr());
            final LogStream output = docker.execStart(execCreation.id());
            final String execOutput = output.readFully();
            System.out.println(execOutput);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void mainaa(String args[]) {

        createNetwork();
    }


    public static void creatContainerWithNetwork() {

        try {
            final DockerClient sut = new DefaultDockerClient("unix:///var/run/docker.sock");
            final String networkName = "networkname";
            final String containerName = "containerWithNetwork";

            final String subnet = "172.20.0.0/16";
            final String ipRange = "172.20.10.0/24";
            final String gateway = "172.20.10.11";
            final IpamConfig ipamConfigToCreate =
                    IpamConfig.create(subnet, ipRange, gateway);
            final Ipam ipamToCreate = Ipam.builder()
                    .driver("default")
                    .config(Lists.newArrayList(ipamConfigToCreate))
                    .build();
            final NetworkConfig networkingConfig = NetworkConfig.builder()
                    .name(networkName)
                    .ipam(ipamToCreate)
                    .build();

            //ContainerConfig.NetworkingConfig.create();
            final NetworkCreation networkCreation =
                    sut.createNetwork(networkingConfig);
            final ContainerConfig containerConfig =
                    ContainerConfig.builder()
                            .image("dockerzook")
                            .cmd("sh", "-c", "while :; do sleep 1; done")
                            .build();
            final ContainerCreation containerCreation = sut.createContainer(containerConfig, containerName);
            sut.startContainer(containerCreation.id());

            // Those are some of the extra parameters that can be set along with the network connection
            final String ip = "172.20.10.1";
            final String dummyAlias = "value-does-not-matter";
            final EndpointConfig endpointConfig = EndpointConfig.builder()
                    .ipamConfig(EndpointConfig.EndpointIpamConfig.builder().ipv4Address(ip).build())
                    .aliases(ImmutableList.<String>of(dummyAlias))
                    .build();

            final NetworkConnection networkConnection = NetworkConnection.builder()
                    .containerId(containerCreation.id())
                    .endpointConfig(endpointConfig)
                    .build();


            Network network = sut.inspectNetwork(networkCreation.id());
            Network.Container networkContainer = network.containers().get(containerCreation.id());
            final ContainerInfo containerInfo = sut.inspectContainer(containerCreation.id());
            final AttachedNetwork attachedNetwork =
                    containerInfo.networkSettings().networks().get(networkName);

            sut.disconnectFromNetwork(containerCreation.id(), networkCreation.id());
            network = sut.inspectNetwork(networkCreation.id());

            sut.stopContainer(containerCreation.id(), 1);
            sut.removeContainer(containerCreation.id());
            sut.removeNetwork(networkCreation.id());


        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 创建网络
     *
     * @param networkName 网络名称
     * @param subnet      子网掩码
     * @param iprange     ip地址范围
     * @param getway      网关
     */
    public void creatNetworkAddrinfo(String networkName, String subnet, String iprange, String getway) {

        //  final DockerClient docker = new DefaultDockerClient("unix:///var/run/docker.sock");

        //创建网络段
        //  final String networkName = "aaabbb55bbpp";
        final IpamConfig ipamConfig = IpamConfig.create(subnet, iprange, getway);
        //   IpamConfig.create("192.168.0.0/24", "192.168.0.0/24", "192.168.0.1");
        final Ipam ipam = Ipam.builder()
                .driver("default")
                .config(singletonList(ipamConfig))
                .build();
        final Map<String, String> labels = ImmutableMap.of(
                "name", "starship", "foo", "bar");
        final NetworkConfig networkConfig =
                NetworkConfig.builder().name(networkName).driver("bridge").checkDuplicate(true).ipam(ipam)
                        .internal(false).enableIPv6(false).labels(labels)
                        .build();

        try {
            NetworkCreation networkCreation = docker.createNetwork(networkConfig);

        } catch (DockerException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


    /**
     * 设置端口映射,开放容器端口
     */

    public HostConfig portMapping(String ports[]) {
        //  final String[] ports = {"2181", "229"};
        final Map<String, List<PortBinding>> portBindings = new HashMap<>();
        for (String port : ports) {
            List<PortBinding> hostPorts = new ArrayList<>();
            hostPorts.add(PortBinding.of("0.0.0.0", port));
            portBindings.put(port, hostPorts);
        }

/* Bind container port 443 to an automatically allocated available host port.
        List<PortBinding> randomPort = new ArrayList<>();
        randomPort.add(PortBinding.randomPort("0.0.0.0"));
        portBindings.put("449", randomPort);*/

        final HostConfig hostConfig = HostConfig.builder().portBindings(portBindings).build();


        return hostConfig;
    }


    /**
     * 创建容器
     *
     * @param ip          ip地址
     * @param name        容器名称
     * @param imageid     镜像
     * @param ports       端口映射
     * @param networkname 网络名称
     */
    public String  creatContainers(String ip, String name, String imageid, String ports[], String networkname) {

        if(ports==null){

            ports[0] = "2999";
        }


        HostConfig hostConfig = portMapping(ports);

        //  final String[] ports = {"2181", "8893","8890"};
        //设置ip地址192.168.0.13
        final EndpointConfig endpointConfig = EndpointConfig.builder()
                //  .ipAddress("192.168.0.12").gateway("192.168.0.1")
                .ipamConfig(EndpointConfig.EndpointIpamConfig.builder().ipv4Address(ip).build())

                .build();
        Map datamap = new HashMap();
        datamap.put(networkname, endpointConfig);
        final ContainerConfig config = ContainerConfig.builder()
                .hostConfig(hostConfig).exposedPorts(ports)
                .networkingConfig(ContainerConfig.NetworkingConfig.create(datamap))
                .image(imageid).cmd("sh", "-c", "while :; do sleep 1; done")
                .build();
        String containerid="";


        try {
            ContainerCreation container = docker.createContainer(config, name);
            containerid=container.id();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return containerid;

    }


    public static void createNetwork() {
        final DockerClient docker = new DefaultDockerClient("unix:///var/run/docker.sock");
   /*
       创建网络段
       final String networkName = "aaabbb55bbpp";
        final IpamConfig ipamConfig =
                IpamConfig.create("192.168.0.0/24", "192.168.0.0/24", "192.168.0.1");
        final Ipam ipam = Ipam.builder()
                .driver("default")
                .config(singletonList(ipamConfig))
                .build();
        final Map<String, String> labels = ImmutableMap.of(
                "name", "starship", "foo", "bar");
        final NetworkConfig networkConfig =
                NetworkConfig.builder().name(networkName).driver("bridge").checkDuplicate(true).ipam(ipam)
                        .internal(false).enableIPv6(false).labels(labels)
                        .build();

        try {
             NetworkCreation networkCreation = docker.createNetwork(networkConfig);
        } catch (DockerException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }*/

        try {


            final String[] ports = {"2181", "229"};
            final Map<String, List<PortBinding>> portBindings = new HashMap<>();
            for (String port : ports) {
                List<PortBinding> hostPorts = new ArrayList<>();
                hostPorts.add(PortBinding.of("0.0.0.0", port));
                portBindings.put(port, hostPorts);
            }

// Bind container port 443 to an automatically allocated available host port.
            List<PortBinding> randomPort = new ArrayList<>();
            randomPort.add(PortBinding.randomPort("0.0.0.0"));
            portBindings.put("449", randomPort);

            final HostConfig hostConfig = HostConfig.builder().portBindings(portBindings).build();


            //设置ip地址192.168.0.13
            final EndpointConfig endpointConfig = EndpointConfig.builder()
                    //  .ipAddress("192.168.0.12").gateway("192.168.0.1")
                    .ipamConfig(EndpointConfig.EndpointIpamConfig.builder().ipv4Address("192.168.0.20").build())

                    .build();

//networkmode指定设置的网络
            //  final HostConfig hostConfig = HostConfig.builder().networkMode("aaapp").build();
            Map datamap = new HashMap();
            datamap.put("aaapp", endpointConfig);
            final ContainerConfig config = ContainerConfig.builder()
                    .hostConfig(hostConfig).exposedPorts(ports)
                    .networkingConfig(ContainerConfig.NetworkingConfig.create(datamap))
                    .image("dockerzook").cmd("sh", "-c", "while :; do sleep 1; done")
                    .build();


            //  final ContainerCreation container = docker.createContainer(config);
            ContainerCreation container = docker.createContainer(config, "181998881");
            //????
            docker.startContainer(container.id());
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    public static void mainpp(String args[]) {
        final DockerClient docker = new DefaultDockerClient("unix:///var/run/docker.sock");
        List data = new ArrayList();
        try {
            List<Container> containers = docker.listContainers(DockerClient.ListContainersParam.allContainers());
            for (int i = 0; i < containers.size(); i++) {
                DockerBean bean = new DockerBean();
                Container container = containers.get(i);
                String state = container.state();//????
                String image = container.image();//????

                com.google.common.collect.ImmutableList<String> listdata = container.names();
                String names = listdata.get(0).toString();
                //   com.google.common.collect.ImmutableSet<AttachedNetwork> networks

                com.google.common.collect.UnmodifiableIterator iterators = container.networkSettings().networks().asMultimap().entries().iterator();
                // Map map = container.networkSettings().networks().asMultimap().asMap();
                ImmutableSet<Map.Entry<String, AttachedNetwork>> networks = container.networkSettings().networks().entrySet();
                AttachedNetwork o = (AttachedNetwork) networks.toArray()[0];

                // ((com.google.common.collect.ImmutableEntry)networks.toArray()[0]).getValue();
                // networks.toArray()[0]
                // ((com.google.common.collect.ImmutableEntry)networks.toArray()[0]).getValue();
                // Iterator<Map.Entry<Integer, String>> it = map.entrySet().iterator();
                while (iterators.hasNext()) {
                    iterators.next();

                    //  com.google.common.collect.SingletonImmutableSet datavalue=(com.google.common.collect.SingletonImmutableSet)entry.getValue();
                    // datavalue.ipAddress();
                    //   System.out.println("key= " + entry.getKey() + " and value= " +  datavalue.ipAddress());
                }

                //.get("bridge");
                String ipaddress = "";
                //((AttachedNetwork) networks.toArray()[0]).ipAddress();//ip??
                // String dates = transferLongToDate("yyyy-MM-dd HH:mm:ss", (Long) container.created());
                bean.setIpaddress(ipaddress);
                bean.setImage(image);
                bean.setState(state);
                // bean.setDates(dates);
                bean.setNames(names);
                data.add(bean);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
