/**
 * <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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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.MapCreateRequest;
import com.zabbix4j.map.MapCreateResponse;
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 MapCreateFromHosts {

    /**
     * 单个节点高度
     */
    public static final int HEIGHT_PER_NODE = 100;

    protected Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 主机分组，key为IP地址前三段
     */
    protected Map<String, HostGroup> groups = new HashMap<String, HostGroup>();

    /**
     * 拓扑图id
     */
    protected Integer mapId;

    /**
     * 创建拓扑图
     *
     * @param name
     *            拓扑图名称
     *
     * @param gatewayIPs
     *            网关节点列表
     * @param layout
     *            布局方式
     * @return 拓扑图id
     * @throws Exception
     *             异常对象
     */
    public int createMap(String name, List<String> gatewayIPs, Layout layout) throws Exception {
        this.groupHosts(gatewayIPs);
        MapCreateRequest request = new MapCreateRequest();
        MapCreateRequest.Params params = request.getParams();
        params.setMap_type(1);
        params.setName(name);
        params.setWidth(1000);
        params.setHeight(1000);

        for (String ipPrefix : groups.keySet()) {
            HostGroup group = groups.get(ipPrefix);
            Host gateway = group.getGateway();
            if (gateway != null) {
                MapElementObject obj = new MapElementObject();
                obj.setLabel("{HOST.NAME}");
                obj.setElementid(gateway.getHostObject().getHostid());
                obj.setElementtype(MapElementObject.ELEMENT_TYPE.HOST.value);
                obj.setX(300);
                obj.setY(gateway.getHostObject().getHostid());
                obj.setIconid_off(155);
                params.addMapElement(obj);
            }
            for (Host host : group.getHosts()) {
                MapElementObject obj = new MapElementObject();
                obj.setLabel("{HOST.NAME}");
                obj.setElementid(host.getHostObject().getHostid());
                obj.setElementtype(MapElementObject.ELEMENT_TYPE.HOST.value);
                obj.setIconid_off(150);
                obj.setX(600);
                obj.setY(host.getHostObject().getHostid());
                params.addMapElement(obj);

            }

        }
        ZabbixApi zabbixApi = Util.getLoginUser().getZabbixApi();
        MapCreateResponse response = zabbixApi.map().create(request);
        //获得mapID
        mapId = response.getResult().getSysmapids().get(0);

        linkAndLayout(layout);
        return mapId;
    }

    /**
     * 创建连接，布局
     *
     * @param layout
     *            布局对象
     * @throws Exception
     *             异常对象
     */
    public void linkAndLayout(Layout layout) throws Exception {
        MapUpdateRequest request = new MapUpdateRequest();
        MapUpdateRequest.Params params = request.getParams();
        params.setSysmapid(mapId);

        prepareLinkAndLayoutData(params);
        layout.doLayout(params, groups);
        ZabbixApi zabbixApi = Util.getLoginUser().getZabbixApi();
        zabbixApi.map().update(request);

    }

    /**
     * 创建连接对象
     *
     * @param from
     *            源
     * @param to
     *            目标
     * @return 连接对象
     */
    protected MapLinkObject newLink(MapElementObject from, MapElementObject to) {
        MapLinkObject link = new MapLinkObject();
        link.setSelementid1(from.getSelementid());
        link.setSelementid2(to.getSelementid());
        return link;
    }

    /**
     * 创建连接对象,布局
     *
     * @param update
     *            拓扑图对象
     * @throws Exception
     *             异常对象
     */
    protected void prepareLinkAndLayoutData(MapUpdateRequest.Params update) throws Exception {
        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());
        ZabbixApi zabbixApi = Util.getLoginUser().getZabbixApi();
        MapGetResponse response = zabbixApi.map().get(request);
        List<MapElementObject> list = response.getResult().get(0).getSelements();
        /**
         * 拓扑图节点Map，key为对于主机的id
         */
        Map<Integer, MapElementObject> elementsMap = new HashMap<Integer, MapElementObject>();

        for (MapElementObject obj : list) {
            elementsMap.put(obj.getY(), obj);
        }

        //        int y = HEIGHT_PER_NODE;
        for (String ipPrefix : groups.keySet()) {
            HostGroup group = groups.get(ipPrefix);
            Host gateway = group.getGateway();
            MapElementObject from = null;
            if (gateway != null) {
                from = elementsMap.get(gateway.getHostObject().getHostid());
                //                from.setY(y + group.getHosts().size() / 2 * HEIGHT_PER_NODE);
                gateway.setMapElementObject(from);
                selements.add(from);
            }
            for (Host host : group.getHosts()) {
                MapElementObject to = elementsMap.get(host.getHostObject().getHostid());
                selements.add(to);
                if (from != null) {
                    links.add(this.newLink(from, to));
                }
                host.setMapElementObject(to);
            }
        }
        //        for (MapElementObject obj : selements) {
        //            List<MapElementURLObject> urlList = new ArrayList<MapElementURLObject>();
        //            MapElementURLObject url = new MapElementURLObject();
        //            url.setName("主机详细信息");
        //            url.setUrl("/cesmonitor/{HOST.ID}");
        //            urlList.add(url);
        //            obj.setUrls(urlList);
        //        }
        update.setLinks(links);
        update.setSelements(selements);
    }

    /**
     * 对所有主机根据网关ip地址进行分组
     *
     * @param gatewayIPs
     *            网关ip地址
     * @throws Exception
     *             异常对象
     */
    public void groupHosts(List<String> gatewayIPs) throws Exception {
        if (gatewayIPs == null || gatewayIPs.size() == 0) {
            //groupHosts();
            throw new RuntimeException("无网关");
        }
        groups.clear();
        for (String ip : gatewayIPs) {
            int index = ip.lastIndexOf('.');
            if (index == -1) {
                throw new RuntimeException("网关IP地址无效：" + gatewayIPs);
            }
            String prefixIP = ip.substring(0, index);
            HostGroup group = new HostGroup();
            group.setGatewayIP(ip);
            groups.put(prefixIP, group);
        }
        HostGetRequest request = new HostGetRequest();
        HostGetRequest.Params params = request.getParams();
        params.setSelectInterfaces(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;
                }
                int index = hi.getIp().lastIndexOf('.');
                String prefixIP = hi.getIp().substring(0, index);
                HostGroup group = groups.get(prefixIP);
                if (group == null) {
                    continue;
                }

                Host host = new Host();
                host.setHostObject(hostObject);

                if (hi.getIp().equals(group.getGatewayIP())) {
                    group.setGateway(host);
                } else {
                    //group.getHosts().add(host);
                    group.addHost(host);
                }
            }
        }
        for (HostGroup group : groups.values()) {
            if (group.getGateway() == null) {
                throw new RuntimeException("网关：" + group.getGatewayIP() + "无对应的主机。");
            }
        }
    }

    /**
     * 自动对所有主机根据默认网关*.*.*.254进行分组
     *
     * @throws Exception
     *             异常对象
     */
    public void groupHosts() throws Exception {
        groups.clear();
        HostGetRequest request = new HostGetRequest();
        HostGetRequest.Params params = request.getParams();
        params.setSelectInterfaces(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;
                }
                int index = hi.getIp().lastIndexOf('.');
                String prefixIP = hi.getIp().substring(0, index);
                HostGroup group = groups.get(prefixIP);
                if (group == null) {
                    group = new HostGroup();
                    groups.put(prefixIP, group);
                }

                Host host = new Host();
                host.setHostObject(hostObject);

                if (hi.getIp().endsWith(".254")) {
                    group.setGateway(host);
                } else {
                    group.getHosts().add(host);
                }
            }
        }
    }

}
