/**
 * <p>Copyright:Copyright(c) 2016</p>
 * <p>Company:上海中信信息发展股份有限公司</p>
 * <p>类更新历史信息</p>
 * @author 张二伟
 * @date 2017-03-19 14:58
 */

package com.cesgroup.cesmonitor.service.map;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.cesgroup.cesmonitor.common.JSON;
import com.cesgroup.cesmonitor.common.Util;
import com.zabbix4j.ZabbixApi;
import com.zabbix4j.ZabbixApiParamter;
import com.zabbix4j.host.HostGetRequest;
import com.zabbix4j.host.HostGetResponse;
import com.zabbix4j.hostinteface.HostInterfaceObject;
import com.zabbix4j.map.MapElementObject;
import com.zabbix4j.map.MapGetRequest;
import com.zabbix4j.map.MapGetResponse;
import com.zabbix4j.map.MapLinkObject;
import com.zabbix4j.map.MapUpdateRequest;

/**
 * 根据主机创建拓扑图
 *
 *
 * @author zhang.erwei
 * @version 1.0.0 2017年5月22日
 */
public class MapAutoCreateUpdate {

    private Map<String, HostGetResponse.Result> hosts = new HashMap<String, HostGetResponse.Result>();

    Map<Integer, Integer> positionY = new HashMap<Integer, Integer>();

    public static final Integer MRAGIN = 200;

    /**
     * 自动创建
     *
     * @param name
     *            拓扑图名称
     * @param coreDeviceIP
     *            核心交换机IP地址
     * @return
     */
    public void update(Integer mapId, String coreDeviceIP, String community) {
        try {

            Device device = new Device();
            device.setIp(coreDeviceIP);
            device.setCommunity(community);
            //            device.setSnmpPort(snmpPort);
            new MapAutoCreatePrepareRalation().getLink(device);
            System.out.println(JSON.toJson(device));
            getHost(device);

            Map<Integer, HostGetResponse.Result> newHosts = addNewHost(mapId);
            System.out.println("新发现主机：" + JSON.toJson(newHosts));

            List<MapLinkObject> links = new ArrayList<MapLinkObject>();
            //            List<MapElementObject> selements = new ArrayList<MapElementObject>();

            ZabbixApi zabbixApi = Util.getLoginUser().getZabbixApi();

            MapGetRequest request = new MapGetRequest();
            MapGetRequest.Params params = request.getParams();
            params.addSysMapId(mapId);
            //        params.setSelectIconMap(ZabbixApiParamter.QUERY.extend.name());
            params.setSelectLinks(ZabbixApiParamter.QUERY.extend.name());
            params.setSelectSelements(ZabbixApiParamter.QUERY.extend.name());
            //        params.setSelectUrls(ZabbixApiParamter.QUERY.extend.name());

            MapGetResponse response = zabbixApi.map().get(request);
            Map<Integer, MapElementObject> map = new HashMap<Integer, MapElementObject>();
            //            List<MapElementObject> list = response.getResult().get(0).getSelements();
            for (MapElementObject obj : response.getResult().get(0).getSelements()) {
                map.put(obj.getElementid(), obj);
            }
            //            //准备元素
            //            for (MapElementObject obj : response.getResult().get(0).getSelements()) {
            //                selements.add(obj);
            //            }
            //准备连接
            for (MapLinkObject obj : response.getResult().get(0).getLinks()) {
                links.add(obj);
            }

            MapUpdateRequest updateRequest = new MapUpdateRequest();
            MapUpdateRequest.Params updateParams = updateRequest.getParams();
            updateParams.setSysmapid(mapId);

            //添加新的连接
            MapElementObject from = map.get(device.getHostid());
            for (String key : device.getLink().keySet()) {
                Device d = device.getLink().get(key);
                if (d.getHostid() == null) {
                    continue;
                }
                if (newHosts.containsKey(device.getHostid()) || newHosts.containsKey(d.getHostid())) {
                    MapElementObject to = map.get(d.getHostid());
                    //                    selements.add(to);
                    //String label = key + ":{" + hosts.get(device.getIp()).getHost() + ":ifOutOctets[" + key + "].last(0)}";
                    String label = "进口：{" + hosts.get(device.getIp()).getHost() + ":ifInOctets[" + key + "].last(0)}";
                    label += "\n出口：{" + hosts.get(device.getIp()).getHost() + ":ifOutOctets[" + key + "].last(0)}";
                    links.add(this.prepareLink(from, to, label));
                }
                this.prepareChildren(d, updateParams, newHosts, links, map);

            }

            updateParams.setLinks(links);
            zabbixApi.map().update(updateRequest);

        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    private Map<Integer, HostGetResponse.Result> addNewHost(Integer mapId) throws Exception {
        Map<Integer, HostGetResponse.Result> newHosts = new HashMap<Integer, HostGetResponse.Result>();
        ZabbixApi zabbixApi = Util.getLoginUser().getZabbixApi();
        Map<Integer, MapElementObject> mapExistElement = new HashMap<Integer, MapElementObject>();

        MapGetRequest request = new MapGetRequest();
        MapGetRequest.Params params = request.getParams();
        params.addSysMapId(mapId);
        //        params.setSelectIconMap(ZabbixApiParamter.QUERY.extend.name());
        params.setSelectLinks(ZabbixApiParamter.QUERY.extend.name());
        params.setSelectSelements(ZabbixApiParamter.QUERY.extend.name());
        //        params.setSelectUrls(ZabbixApiParamter.QUERY.extend.name());

        MapGetResponse response = zabbixApi.map().get(request);
        List<MapElementObject> list = response.getResult().get(0).getSelements();

        for (MapElementObject obj : list) {
            mapExistElement.put(obj.getElementid(), obj);
        }

        MapUpdateRequest updateRequest = new MapUpdateRequest();
        MapUpdateRequest.Params updateParams = updateRequest.getParams();
        updateParams.setSysmapid(mapId);

        //List<MapLinkObject> links = new ArrayList<MapLinkObject>();
        List<MapElementObject> selements = new ArrayList<MapElementObject>();
        //准备元素
        for (MapElementObject obj : list) {
            selements.add(obj);
        }
        //查找新增加主机
        int x = 0;
        int y = 50;
        int n = 0;
        for (HostGetResponse.Result h : hosts.values()) {
            if (!mapExistElement.containsKey(h.getHostid())) {
                MapElementObject mapChild = new MapElementObject();
                mapChild.setLabel("{HOST.NAME}");
                mapChild.setElementid(h.getHostid());
                mapChild.setElementtype(MapElementObject.ELEMENT_TYPE.HOST.value);
                x = 50 * ++n;
                if (x - 100 > response.getResult().get(0).getWidth()) {
                    n = 0;
                    x = 50 * ++n;
                    y += 100;
                }

                mapChild.setX(50 * (newHosts.size() + 1));
                mapChild.setY(y);
                mapChild.setIconid_off(155);
                selements.add(mapChild);
                newHosts.put(h.getHostid(), h);
            }
        }
        updateParams.setSelements(selements);
        zabbixApi.map().update(updateRequest);
        return newHosts;
    }

    private void prepareChildren(Device device, MapUpdateRequest.Params mapUpdateRequest,
        Map<Integer, HostGetResponse.Result> newHosts, List<MapLinkObject> links, Map<Integer, MapElementObject> map) {

        MapElementObject from = map.get(device.getHostid());

        //for (Device d : device.getLink().values()) {
        for (String key : device.getLink().keySet()) {
            Device d = device.getLink().get(key);
            if (d.getHostid() == null) {
                continue;
            }

            MapElementObject to = map.get(d.getHostid());
            if (newHosts.containsKey(device.getHostid()) || newHosts.containsKey(d.getHostid())) {
                String label = "进口：{" + hosts.get(device.getIp()).getHost() + ":ifInOctets[" + key + "].last(0)}";
                label += "\n出口：{" + hosts.get(device.getIp()).getHost() + ":ifOutOctets[" + key + "].last(0)}";
                links.add(this.prepareLink(from, to, label));
            }
            this.prepareChildren(d, mapUpdateRequest, newHosts, links, map);
        }

    }

    private MapLinkObject prepareLink(MapElementObject from, MapElementObject to, String lable) {
        MapLinkObject link = new MapLinkObject();
        link.setSelementid1(from.getSelementid());
        link.setSelementid2(to.getSelementid());
        link.setLabel(lable);
        return link;
    }

    //    private Map<Integer, MapElementObject> getMapElementObject(int mapId) throws Exception {
    //        ZabbixApi zabbixApi = Util.getLoginUser().getZabbixApi();
    //        List<MapLinkObject> links = new ArrayList<MapLinkObject>();
    //        List<MapElementObject> selements = new ArrayList<MapElementObject>();
    //
    //        MapGetRequest request = new MapGetRequest();
    //        MapGetRequest.Params params = request.getParams();
    //        params.addSysMapId(mapId);
    //        //        params.setSelectIconMap(ZabbixApiParamter.QUERY.extend.name());
    //        params.setSelectLinks(ZabbixApiParamter.QUERY.extend.name());
    //        params.setSelectSelements(ZabbixApiParamter.QUERY.extend.name());
    //        //        params.setSelectUrls(ZabbixApiParamter.QUERY.extend.name());
    //
    //        MapGetResponse response = zabbixApi.map().get(request);
    //        List<MapElementObject> list = response.getResult().get(0).getSelements();
    //        Map<Integer, MapElementObject> map = new HashMap<Integer, MapElementObject>();
    //        for (MapElementObject obj : list) {
    //            map.put(obj.getElementid(), obj);
    //        }
    //        return map;
    //    }

    //    /**
    //     * 查询主机
    //     *
    //     * @throws Exception
    //     *             异常对象
    //     */
    //    private void getHost() throws Exception {
    //        HostGetRequest request = new HostGetRequest();
    //        HostGetRequest.Params params = request.getParams();
    //        params.setSelectInterfaces(ZabbixApiParamter.QUERY.extend.name());
    //        params.setSelectMacros(ZabbixApiParamter.QUERY.extend.name());
    //        ZabbixApi zabbixApi = Util.getLoginUser().getZabbixApi();
    //        HostGetResponse response = zabbixApi.host().get(request);
    //        for (HostGetResponse.Result hostObject : response.getResult()) {
    //            for (HostInterfaceObject hi : hostObject.getInterfaces()) {
    //                if (hi.getInterfaceid() == null) {
    //                    continue;
    //                }
    //                hosts.put(hi.getIp(), hostObject);
    //            }
    //        }
    //    }

    /**
     * 查询主机
     *
     * @throws Exception
     *             异常对象
     */
    private void getHost(Device device) throws Exception {
        HostGetRequest request = new HostGetRequest();
        HostGetRequest.Params params = request.getParams();
        params.setSelectInterfaces(ZabbixApiParamter.QUERY.extend.name());
        params.setSelectMacros(ZabbixApiParamter.QUERY.extend.name());
        ZabbixApi zabbixApi = Util.getLoginUser().getZabbixApi();
        HostGetResponse response = zabbixApi.host().get(request);
        for (HostGetResponse.Result hostObject : response.getResult()) {
            for (HostInterfaceObject hi : hostObject.getInterfaces()) {
                if (hi.getInterfaceid() == null) {
                    continue;
                }
                if (device.containIP(hi.getIp(), hi.getHostid())) {
                    hosts.put(hi.getIp(), hostObject);
                }
            }
        }
    }
}
