package com.elephant.framework.galaxy.aroad.trafficbasic.utils;

import com.elephant.framework.galaxy.aroad.trafficbasic.domain.LuKeBridge;
import com.elephant.framework.galaxy.aroad.trafficbasic.domain.LuKeHighWay;
import com.google.gson.Gson;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.transport.client.PreBuiltTransportClient;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

/**
* @Description:  自定义elasticsearch工具类，
 * 1、实现elasticsearch集群的连接
 * 2、路段、桥梁索引数据插入
 * 3、路段、桥梁分词检索
 * 4、分词检索出来的数据是否是路段数据或者桥梁数据
* @Param:
* @return:
* @Author: dongjili
* @Date:
*/
public class EsUtil_fanshe {
    public static TransportClient transportClient;
    public static Gson gson = new Gson();

    /**
     * @Description: 创建连接
     * @Param:
     * @return: transportClient
     * @Author: dongjili
     * @Date:
     */
    public static TransportClient getClient() throws Exception {
        Settings settings = Settings.builder().put("cluster.name", "myes").build();
        if (transportClient == null) {
            synchronized (EsUtil_fanshe.class) {
                // 创建Client连接对象
                transportClient = new PreBuiltTransportClient(settings)
                        .addTransportAddress(new TransportAddress(InetAddress.getByName("192.168.6.100"), 9300))
                        .addTransportAddress(new TransportAddress(InetAddress.getByName("192.168.6.110"), 9300))
                        .addTransportAddress(new TransportAddress(InetAddress.getByName("192.168.6.120"), 9300));
            }

        }

        return transportClient;
    }

    /**
     * @Description: 桥梁索引表插入数据
     * @Param:
     * @return:
     * @Author: dongjili
     * @Date:
     */
    public static void indexBridge(List<LuKeBridge> luKeBridges) throws Exception {
        // 建立文档
        //prepareIndex一次创建一个索引，bulkIndex就可以将多个文档合并在一起之后，发送一次请求
        BulkRequestBuilder bulk = getClient().prepareBulk();
        for (LuKeBridge luKeBridge : luKeBridges) {
            String json = gson.toJson(luKeBridge);
            IndexRequestBuilder requestBuilder = transportClient.prepareIndex("basicbridgedata", "2018", luKeBridge.getId()).setSource(json, XContentType.JSON);
            bulk.add(requestBuilder);
        }
        BulkResponse bulkItemResponses = bulk.get();
        System.out.println(bulkItemResponses.status());

    }

    /**
     * @Description: 路段索引表插入数据
     * @Param:
     * @return:
     * @Author: dongjili
     * @Date:
     */
    public static void indexHighWay(List<LuKeHighWay> luKeHighWays) throws Exception {
        // 建立文档
        BulkRequestBuilder bulk = getClient().prepareBulk();
        for (LuKeHighWay luKeHighWay : luKeHighWays) {
            String json = gson.toJson(luKeHighWay);
            IndexRequestBuilder requestBuilder = transportClient.prepareIndex("basichighwaydata", "2018", luKeHighWay.getId()).setSource(json, XContentType.JSON);
            bulk.add(requestBuilder);
        }
        BulkResponse bulkItemResponses = bulk.get();
        //System.out.println(bulkItemResponses.status());
    }
/**
* @Description: 释放资源
* @Param:
* @return:
* @Author: dongjili
* @Date:
*/
    public static void close() {
        //释放资源
        if (transportClient != null) {
            transportClient.close();
        }
    }

    /**
     * @Description: 桥梁全字段查询
     * @Param:
     * @return: ArrayList<LuKeBridge> luKeBridges
     * @Author: dongjili
     * @Date:
     */
    public static ArrayList<LuKeBridge> queryBridge(String keyword, String index, String type, int start, int row) throws Exception {
        // 搜索数据
        SearchRequestBuilder searchRequestBuilder = getClient().prepareSearch(index).setTypes(type).setFrom(start).setSize(row);
        //isNotBlank(str) 等价于 str != null && str.length > 0 && str.trim().length> 0(去掉字符串两端的多余的空格的长度）
        if (org.apache.commons.lang.StringUtils.isNotBlank(keyword)) {
            //multiMatchQuery多个字段匹配某一个值
            //multiMatchQuery(text,fields)其中的fields是字段的名字，可以写好几个，每一个中间用逗号分隔
            searchRequestBuilder.setQuery(QueryBuilders.multiMatchQuery(keyword, "id",
                    "qiaoliangmingcheng",
                    "qiaoliangdaima"
            ));
        }
        String[] bridgeNames = {"id", "qiaoliangmingcheng",
                "qiaoliangdaima"};
        SearchResponse response = searchRequestBuilder.get();
        //获取命中次数，查询结果有多少对象
        SearchHits hits = response.getHits();
        ArrayList<LuKeBridge> luKeBridges = new ArrayList<>();
        for (SearchHit hit : hits) {
            //System.out.println(hit.getSourceAsString());
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            //LuKeBridge luKeBridge = new LuKeBridge();
            //获取该类在堆区的Class对象
            Class<?> clazz = Class.forName("com.elephant.framework.galaxy.aroad.trafficbasic.domain.LuKeBridge");
            //获取私有的构造方法
            Constructor<?> constructor = clazz.getDeclaredConstructor();
            //暴力破解
            constructor.setAccessible(true);
            //实例化对象
            LuKeBridge luKeBridge = (LuKeBridge) constructor.newInstance();
            //获得私有的属性对象
            Field[] beanFiled = clazz.getDeclaredFields();
            luKeBridge.setId(hit.getId());
            for (int a = 1; a < bridgeNames.length; a++) {
                //暴力破解
                beanFiled[a].setAccessible(true);
                //把查询到的每一个字段的值赋给luKeBridge的每一个属性
                beanFiled[a].set(luKeBridge, sourceAsMap.get(bridgeNames[a]) == null ? "" : sourceAsMap.get(bridgeNames[a]).toString());
            }
            luKeBridges.add(luKeBridge);
        }
        return luKeBridges;
    }

    /**
     * @Description: 路段全字段查询
     * @Param:
     * @return: ArrayList<LuKeHighWay> lukehighways
     * @Author: dongjili
     * @Date:
     */
    public static ArrayList<LuKeHighWay> queryHighWay(String keyword, String index, String type, int start, int row) throws Exception {
        //搜索数据
        SearchRequestBuilder searchRequestBuilder = getClient().prepareSearch(index).setTypes(type).setFrom(start).setSize(row);
        //isNotBlank(str) 等价于 str != null && str.length > 0 && str.trim().length> 0(去掉字符串两端的多余的空格的长度）
        if (org.apache.commons.lang.StringUtils.isNotBlank(keyword)) {
            //multiMatchQuery多个字段匹配某一个值
            //multiMatchQuery(text,fields)其中的fields是字段的名字，可以写好几个，每一个中间用逗号分隔
            searchRequestBuilder.setQuery(QueryBuilders.multiMatchQuery(keyword, "id",
                    "luxianbianhao",
                    "luxianmingcheng",
                    "qidianmingcheng",
                    "zhidianmingcheng"
            ));
        }
        String[] highwayNames = {"id",
                "luxianbianhao",
                "luxianmingcheng",
                "qidianmingcheng",
                "zhidianmingcheng"
        };
        SearchResponse response = searchRequestBuilder.get();
        //获取命中次数，查询结果有多少对象
        SearchHits hits = response.getHits();
        ArrayList<LuKeHighWay> lukehighways = new ArrayList<>();
        for (SearchHit hit : hits) {
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            //LuKeHighWay luKeHighWay = new LuKeHighWay();
            //获取该类在堆区的Class对象
            Class<?> clazz = Class.forName("com.elephant.framework.galaxy.aroad.trafficbasic.domain.LuKeHighWay");
            //获取私有的构造方法
            Constructor<?> constructor = clazz.getDeclaredConstructor();
            //暴力破解
            constructor.setAccessible(true);
            //实例化对象
            LuKeHighWay luKeHighWay = (LuKeHighWay) constructor.newInstance();
            //获取私有的属性字段
            Field[] beanFiled = clazz.getDeclaredFields();
            luKeHighWay.setId(hit.getId());
            for (int a = 1; a < highwayNames.length; a++) {
                //暴力破解
                beanFiled[a].setAccessible(true);
                //给路段属性复制
                beanFiled[a].set(luKeHighWay, sourceAsMap.get(highwayNames[a]) == null ? "" : sourceAsMap.get(highwayNames[a]).toString());
            }
            lukehighways.add(luKeHighWay);
        }
        return lukehighways;
    }

    /**
     * @Description: 获取路段所有的id
     * @Param:
     * @return: 返回查询的路段所有id或桥梁所有id
     * @Author: dongjili
     * @Date:
     */
    public static ArrayList<String> queryIds(String index, String type, int start, int row) throws Exception {
        //定义集合封装查询的ids
        ArrayList<String> trafficIds = new ArrayList<>();
        //搜索数据
        SearchRequestBuilder searchRequestBuilder = getClient().prepareSearch(index).setTypes(type).setFrom(start).setSize(row);
        //matchAllQuery查询所有数据
        searchRequestBuilder.setQuery(QueryBuilders.matchAllQuery());
        SearchResponse response = searchRequestBuilder.get();
        SearchHits hits = response.getHits();
        for (SearchHit hit : hits) {
            String id = hit.getId();
            trafficIds.add(id);
        }

        return trafficIds;
    }

/**
* @Description: 分词检索出来的数据是否是路段数据或者桥梁数据
* @Param:
* @return:
* @Author: dongjili
* @Date:
*/
    public static String ifInclude(ArrayList<String> basicbridgeIds, ArrayList<String> basichighwayIds, ArrayList<LuKeBridge> luKeBridges, ArrayList<LuKeHighWay> lukehighways) {
        ArrayList<String> trafficIds = new ArrayList<>();
        //查询所有的桥梁id封装在trafficIds集合中
        for (LuKeBridge luKeBridge : luKeBridges) {
            String luKeBridgeId = luKeBridge.getId();
            trafficIds.add(luKeBridgeId);
        }
        //查询所有的路段id封装在trafficIds集合中
        for (LuKeHighWay lukehighway : lukehighways) {
            String lukehighwayId = lukehighway.getId();
            trafficIds.add(lukehighwayId);
        }

        HashSet<String> hashSet = new HashSet<>();
        //判断桥梁、路段全字段查询出来的id是否在trafficIds集合中，返回各字段名称
        for (String trafficId : trafficIds) {
            //System.out.println(trafficId);
            if (basicbridgeIds.contains(trafficId)) {
                hashSet.add("桥梁明细表");
                continue;
            } else if (basichighwayIds.contains(trafficId)) {
                hashSet.add("路段明细表");
                continue;
            }
        }
        return hashSet.toString();
    }
}

