package com.artfess.es.unit;

import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
import org.elasticsearch.action.admin.indices.refresh.RefreshResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetFieldMappingsRequest;
import org.elasticsearch.client.indices.GetFieldMappingsResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.client.indices.GetIndexTemplatesRequest;
import org.elasticsearch.client.indices.GetIndexTemplatesResponse;
import org.elasticsearch.client.indices.GetMappingsRequest;
import org.elasticsearch.client.indices.GetMappingsResponse;
import org.elasticsearch.client.indices.IndexTemplateMetaData;
import org.elasticsearch.cluster.metadata.MappingMetaData;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

@Service
public class ElasticIndexApplicationImpl implements ElasticIndexApplication {

    private static final Logger log = LoggerFactory.getLogger(ElasticSearchApplicationImpl.class);

    private final RestHighLevelClient restHighLevelClient;

    @Autowired
    public ElasticIndexApplicationImpl(RestHighLevelClient restHighLevelClient) {
        this.restHighLevelClient = restHighLevelClient;
    }

    @Override
    public boolean isIndexExist(String indexName) {

        GetIndexRequest request = new GetIndexRequest(indexName);

        boolean exists = false;
        try {
            exists = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
            log.error("索引信息获取发生异常！");
        }

        return exists;
    }

    @Override
    public List<Map<String, Object>> getIndexMapping(String indexName) {
        GetMappingsRequest request = new GetMappingsRequest();
        request.indices(indexName);
        try {
            GetMappingsResponse getMappingResponse = restHighLevelClient.indices().getMapping(request, RequestOptions.DEFAULT);

            Map<String, MappingMetaData> allMappings = getMappingResponse.mappings();
            if(allMappings != null){
                List<Map<String, Object>> list = new ArrayList<>();
                Iterator<String> iterator =  allMappings.keySet().iterator();
                Map<String,Object> map ;
                while (iterator.hasNext()){
                    map = new HashMap<>();
                    String  indexName1= iterator.next();
                    MappingMetaData indexMapping = allMappings.get(indexName1);
                    Map<String, Object> mapping = indexMapping.sourceAsMap();
                    map.put("indexName",indexName1);
                    map.put("mapping",mapping);
                    list.add(map);

                }
                return list;
            }
            return null;
        } catch (IOException e) {
            e.printStackTrace();
            log.error("获取索引的字段信息发生异常！");
            return null;
        }

    }
    /**
     * 获取指定索引的字段映射信息
     * @param indexName 索引名称
     * @param fieldNames 字段名集合
     * @return 索引字段的映射信息
     */
    @Override
    public Map<String, Map<String, GetFieldMappingsResponse.FieldMappingMetaData>> getIndexFieldMapping(String indexName,List<String> fieldNames) {
        GetFieldMappingsRequest request = new GetFieldMappingsRequest();
        request.indices(indexName);
        if(fieldNames != null){
            for (String str:fieldNames) {
                request.fields(str);
            }
        }

        try {
            GetFieldMappingsResponse getFieldMappingResponse = restHighLevelClient.indices().getFieldMapping(request, RequestOptions.DEFAULT);

            return getFieldMappingResponse.mappings();
        } catch (IOException e) {
            e.printStackTrace();
            log.error("获取索引的字段信息发生异常！");
            return null;
        }

    }

    public boolean createIndex(String newIndexName,String indexTemplateName) throws IOException {
        boolean boo = isIndexExist(newIndexName);
        if(boo){
            return false;
        }
        CreateIndexRequest createIndexRequest = new CreateIndexRequest(newIndexName);
        GetIndexTemplatesRequest getIndexTemplatesRequest = new GetIndexTemplatesRequest(indexTemplateName);
        GetIndexTemplatesResponse getIndexTemplatesResponse = this.restHighLevelClient.indices().getIndexTemplate(getIndexTemplatesRequest, RequestOptions.DEFAULT);
        List<IndexTemplateMetaData> indexTemplates = getIndexTemplatesResponse.getIndexTemplates();
        if(indexTemplates.size() != 0){
            IndexTemplateMetaData indexTemplateMetaData = indexTemplates.get(0);
            MappingMetaData mappings = indexTemplateMetaData.mappings();
            Settings settings = indexTemplateMetaData.settings();
            createIndexRequest.mapping(mappings.getSourceAsMap());
            createIndexRequest.settings(settings);
        }
        CreateIndexResponse createIndexResponse = this.restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
        return createIndexResponse.isAcknowledged();
    }

    public List<IndexTemplateMetaData> getIndexTemplate(String indexTemplateName) throws IOException {
        GetIndexTemplatesRequest getIndexTemplatesRequest = new GetIndexTemplatesRequest(indexTemplateName);
        GetIndexTemplatesResponse getIndexTemplatesResponse = this.restHighLevelClient.indices().getIndexTemplate(getIndexTemplatesRequest, RequestOptions.DEFAULT);
        List<IndexTemplateMetaData> indexTemplates = getIndexTemplatesResponse.getIndexTemplates();
        return indexTemplates;

    }

    public boolean createIndex(String newIndexName, Settings settings, XContentBuilder xContentBuilder) throws IOException {
        boolean boo = isIndexExist(newIndexName);
        if(boo){
            return false;
        }
        CreateIndexRequest createIndexRequest = new CreateIndexRequest(newIndexName);
        createIndexRequest.mapping(xContentBuilder);
        createIndexRequest.settings(settings);
        CreateIndexResponse createIndexResponse = this.restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
        return createIndexResponse.isAcknowledged();
    }

    /**
     * 刷新指定的索引
     * @param indexName 索引名称
     * @throws IOException
     */
    public RefreshResponse refreshIndex(String... indexName) throws IOException {
        RefreshRequest refreshRequest = new RefreshRequest(indexName);
        return this.restHighLevelClient.indices().refresh(refreshRequest, RequestOptions.DEFAULT);
    }

    /**
     * 刷新所有索引
     * @throws IOException
     */
    public RefreshResponse refreshIndex() throws IOException {
        RefreshRequest refreshRequest = new RefreshRequest();
        return this.restHighLevelClient.indices().refresh(refreshRequest, RequestOptions.DEFAULT);
    }
}
