package com.ruoyi.biemo.elasticsearch.util;

import com.ruoyi.biemo.elasticsearch.entity.ElasticsearchMonitorProperties;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.time.Duration;

/**
 * EliasticSearch连接池工厂对象
 */
@Slf4j
@Component
public class ElasticsearchClientPoolFactory implements PooledObjectFactory<RestHighLevelClient> {

    @Autowired
    private ElasticsearchMonitorProperties esProperties;

    @Override
    public void activateObject(PooledObject<RestHighLevelClient> arg0) throws Exception {

    }

    /**
     * 销毁对象
     */
    @Override
    public void destroyObject(PooledObject<RestHighLevelClient> pooledObject) throws Exception {
        RestHighLevelClient highLevelClient = pooledObject.getObject();
        highLevelClient.close();
    }

    /**
     * 生产对象
     */
    @Override
    public PooledObject<RestHighLevelClient> makeObject() {
        RestHighLevelClient restHighLevelClient = null;
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
//        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(esProperties.getUserName(), esProperties.getPassword()));
        try {
            String[] urlArr = esProperties.getAddress().split(",");
            HttpHost[] httpPostArr = new HttpHost[urlArr.length];
            for (int i = 0; i < urlArr.length; i++) {
                HttpHost httpHost = new HttpHost(urlArr[i].split(":")[0].trim(),
                        Integer.parseInt(urlArr[i].split(":")[1].trim()), "http");
                httpPostArr[i] = httpHost;
            }

            RestClientBuilder builder = RestClient.builder(httpPostArr);


            // 异步httpclient连接延时配置
            builder.setRequestConfigCallback(requestConfigBuilder -> {
                requestConfigBuilder.setConnectTimeout(esProperties.getConnectTimeout());
                requestConfigBuilder.setSocketTimeout(esProperties.getSocketTimeout());
                requestConfigBuilder.setConnectionRequestTimeout(esProperties.getConnectionRequestTimeout());
                return requestConfigBuilder;
            });

            // 异步httpclient连接数配置
            builder.setHttpClientConfigCallback(httpClientBuilder -> {
                httpClientBuilder.setMaxConnTotal(esProperties.getMaxConnectNum());
                httpClientBuilder.setMaxConnPerRoute(esProperties.getMaxConnectPerRoute());
                // httpclient保活策略
                httpClientBuilder.setKeepAliveStrategy(((response, context) -> Duration.ofMinutes(5).toMillis()));
                httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
                return httpClientBuilder;
            });
            restHighLevelClient = new RestHighLevelClient(builder);
        } catch (Exception e) {
            log.error("ElasticsearchClientPoolFactory.makeObject error:", e);
        }
        return new DefaultPooledObject<RestHighLevelClient>(restHighLevelClient);
    }

    @Override
    public void passivateObject(PooledObject<RestHighLevelClient> arg0) throws Exception {
    }

    @Override
    public boolean validateObject(PooledObject<RestHighLevelClient> arg0) {
        return true;
    }
}


